// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import {FormattedMessage} from 'react-intl';

import {Constants} from 'utils/constants';
import {getSiteURL} from 'utils/url';
import {t} from 'utils/i18n';
import {
    ldapTest, invalidateAllCaches, reloadConfig, testS3Connection,
    removeIdpSamlCertificate, uploadIdpSamlCertificate,
    removePrivateSamlCertificate, uploadPrivateSamlCertificate,
    removePublicSamlCertificate, uploadPublicSamlCertificate,
    invalidateAllEmailInvites, testSmtp, testSiteURL, getSamlMetadataFromIdp, setSamlIdpCertificateFromMetadata,
} from 'actions/admin_actions';
import SystemAnalytics from 'components/analytics/system_analytics';
import TeamAnalytics from 'components/analytics/team_analytics';
import PluginManagement from 'components/admin_console/plugin_management';
import CustomPluginSettings from 'components/admin_console/custom_plugin_settings';

import {trackEvent} from 'actions/diagnostics_actions.jsx';

import Audits from './audits';
import CustomUrlSchemesSetting from './custom_url_schemes_setting.jsx';
import CustomEnableDisableGuestAccountsSetting from './custom_enable_disable_guest_accounts_setting';
import LicenseSettings from './license_settings';
import PermissionSchemesSettings from './permission_schemes_settings';
import PermissionSystemSchemeSettings from './permission_schemes_settings/permission_system_scheme_settings';
import PermissionTeamSchemeSettings from './permission_schemes_settings/permission_team_scheme_settings';
import SystemUsers from './system_users';
import SystemUserDetail from './system_user_detail';
import ServerLogs from './server_logs';
import BrandImageSetting from './brand_image_setting/brand_image_setting.jsx';
import GroupSettings from './group_settings/group_settings.jsx';
import GroupDetails from './group_settings/group_details';
import TeamSettings from './team_channel_settings/team';
import TeamDetails from './team_channel_settings/team/details';
import ChannelSettings from './team_channel_settings/channel';
import ChannelDetails from './team_channel_settings/channel/details';
import PasswordSettings from './password_settings.jsx';
import PushNotificationsSettings from './push_settings.jsx';
import DataRetentionSettings from './data_retention_settings.jsx';
import MessageExportSettings from './message_export_settings.jsx';
import DatabaseSettings from './database_settings.jsx';
import ElasticSearchSettings from './elasticsearch_settings.jsx';
import BleveSettings from './bleve_settings.jsx';
import ClusterSettings from './cluster_settings.jsx';
import CustomTermsOfServiceSettings from './custom_terms_of_service_settings';
import SessionLengthSettings from './session_length_settings';
import LDAPFeatureDiscovery from './feature_discovery/ldap.tsx';
import SAMLFeatureDiscovery from './feature_discovery/saml.tsx';

import * as DefinitionConstants from './admin_definition_constants';

const FILE_STORAGE_DRIVER_LOCAL = 'local';
const FILE_STORAGE_DRIVER_S3 = 'amazons3';
const MEBIBYTE = Math.pow(1024, 2);

const SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA1 = 'RSAwithSHA1';
const SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA256 = 'RSAwithSHA256';
const SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA512 = 'RSAwithSHA512';

const SAML_SETTINGS_CANONICAL_ALGORITHM_C14N = 'Canonical1.0';
const SAML_SETTINGS_CANONICAL_ALGORITHM_C14N11 = 'Canonical1.1';

// admin_definitions data structure define the autogenerated admin_console
// section. It defines the structure of the menu based on sections, subsections
// and pages. Each page contains an schema which defines a component to use for
// render the entire section or the name of the section (name and
// name_default), the section in the config file (id), and a list of options to
// configure (settings).
//
// All text fiels contains a transation key, and the <field>_default string are the
// default text when the translation is still not avaiable (the english version
// of the text).
//
// We can define different types of settings configuration widgets:
//
// Widget:
//   - type: which define the widget type.
//   - label (and label_default): which define the main text of the setting.
//   - isDisabled: a function which receive current config, the state of the page and the license.
//   - isHidden: a function which receive current config, the state of the page and the license.
//
// Custom Widget (extends from Widget):
//   - component: The component used to render the widget
//
// JobsTable Widget (extends from Widget):
//   - job_type: The kind of job from Constants.JobTypes
//   - render_job: Function to convert a job object into a react component.
//
// Banner Widget (extends from Widget):
//   - banner_type: The type of banner (options: info or warning)
//
// Setting Widget (extends from Widget):
//   - key: The key to store the configuration in the config file.
//   - help_text (and help_text_default): Long description of the field.
//   - help_text_markdown: True if the translation text contains markdown.
//   - help_text_values: Values to fill the translation (if needed).
//
// Bool Widget (extends from Setting Widget)
//
// Number Widget (extends from Setting Widget)
//
// Color Widget (extends from Setting Widget)
//
// Text Widget (extends from Setting Widget)
//   - placeholder (and placeholder_default): Placeholder text to show in the input.
//   - dynamic_value: function that generate the value of the field based on the current value, the config, the state and the license.
//   - default_value: function that generate the default value of the field based on the config, the state and the license.
//   - max_length: The maximun length allowed
//
// Button Widget (extends from Setting Widget)
//   - action: A redux action to execute on click.
//   - error_message (and error_message_default): Error to show if action doesn't work.
//   - success_message (and success_message_default): Success message to show if action doesn't work.
//
// Language Widget (extends from Setting Widget)
//   - multiple: If you can select multiple languages.
//   - no_result (and no_result_default): Text to show on not results found (only for multiple = true).
//   - not_present (and not_present_default): Text to show when the default language is not present (only for multiple = true).
//
// Dropdown Widget (extends from Setting Widget)
//   - options: List of options of the dropdown (each options has value, display_name, display_name_default and optionally help_text, help_text_default, help_text_values, help_text_markdown fields).
//
// Permissions Flag (extends from Setting Widget)
//   - permissions_mapping_name: A permission name in the utils/policy_roles_adapter.js file.
//
// FileUpload (extends from Setting Widget)
//   - remove_help_text (and remove_help_text_default):  Long description of the field when a file is uploaded.
//   - remove_help_text_markdown: True if the translation text contains markdown.
//   - remove_help_text_values: Values to fill the translation (if needed).
//   - remove_button_text (and remove_button_text_default): Button text for remove when the file is uploaded.
//   - removing_text (and removing_text_default): Text shown while the system is removing the file.
//   - uploading_text (and uploading_text_default): Text shown while the system is uploading the file.
//   - upload_action: An store action to upload the file.
//   - remove_action: An store action to remove the file.
//   - fileType: A list of extensions separated by ",". E.g. ".jpg,.png,.gif".

export const it = {
    isnt: (func) => (config, state, license, enterpriseReady) => !func(config, state, license, enterpriseReady),
    both: (...funcs) => (config, state, license) => {
        for (const func of funcs) {
            if (!func(config, state, license)) {
                return false;
            }
        }
        return true;
    },
    either: (...funcs) => (config, state, license, enterpriseReady) => {
        for (const func of funcs) {
            if (func(config, state, license, enterpriseReady)) {
                return true;
            }
        }
        return false;
    },
    stateMatches: (key, regex) => (config, state) => state[key].match(regex),
    stateEquals: (key, value) => (config, state) => state[key] === value,
    stateIsTrue: (key) => (config, state) => Boolean(state[key]),
    stateIsFalse: (key) => (config, state) => !state[key],
    configIsTrue: (group, setting) => (config) => Boolean(config[group][setting]),
    configIsFalse: (group, setting) => (config) => !config[group][setting],
    enterpriseReady: (config, state, license, enterpriseReady) => enterpriseReady,
    licensed: (config, state, license) => license.IsLicensed === 'true',
    licensedForFeature: (feature) => (config, state, license) => license.IsLicensed && license[feature] === 'true',
};

const AdminDefinition = {
    about: {
        icon: 'fa-info-circle',
        sectionTitle: t('admin.sidebar.about'),
        sectionTitleDefault: 'About',
        license: {
            url: 'about/license',
            title: t('admin.sidebar.license'),
            title_default: 'Edition and License',
            isHidden: it.either(
                it.isnt(it.enterpriseReady),
                it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            ),
            searchableStrings: [
                'admin.license.title',
                'admin.license.uploadDesc',
                'admin.license.keyRemove',
                'admin.license.edition',
                'admin.license.type',
                'admin.license.key',
                'Mattermost Enterprise Edition. Unlock enterprise features in this software through the purchase of a subscription from ',
                'This software is offered under a commercial license.\n\nSee ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.',
            ],
            schema: {
                id: 'LicenseSettings',
                component: LicenseSettings,
            },
        },
    },
    reporting: {
        icon: 'fa-bar-chart',
        sectionTitle: t('admin.sidebar.reporting'),
        sectionTitleDefault: 'Reporting',
        system_analytics: {
            url: 'reporting/system_analytics',
            title: t('admin.sidebar.siteStatistics'),
            title_default: 'Site Statistics',
            searchableStrings: [
                'analytics.system.title',
                'analytics.system.totalPosts',
                'analytics.system.activeUsers',
                'analytics.system.totalSessions',
                'analytics.system.totalCommands',
                'analytics.system.totalIncomingWebhooks',
                'analytics.system.totalOutgoingWebhooks',
                'analytics.system.totalWebsockets',
                'analytics.system.totalMasterDbConnections',
                'analytics.system.totalReadDbConnections',
                'analytics.system.postTypes',
                'analytics.system.channelTypes',
                'analytics.system.totalUsers',
                'analytics.system.totalTeams',
                'analytics.system.totalChannels',
                'analytics.system.dailyActiveUsers',
                'analytics.system.monthlyActiveUsers',
            ],
            schema: {
                id: 'SystemAnalytics',
                component: SystemAnalytics,
            },
        },
        team_statistics: {
            url: 'reporting/team_statistics',
            title: t('admin.sidebar.teamStatistics'),
            title_default: 'Team Statistics',
            searchableStrings: [
                ['analytics.team.title', {team: ''}],
                'analytics.system.info',
                'analytics.team.totalPosts',
                'analytics.team.activeUsers',
                'analytics.team.totalUsers',
                'analytics.team.publicChannels',
                'analytics.team.privateGroups',
                'analytics.team.recentUsers',
                'analytics.team.newlyCreated',
            ],
            schema: {
                id: 'TeamAnalytics',
                component: TeamAnalytics,
            },
        },
        server_logs: {
            url: 'reporting/server_logs',
            title: t('admin.sidebar.logs'),
            title_default: 'Server Logs',
            searchableStrings: [
                'admin.logs.bannerDesc',
                'admin.logs.title',
            ],
            schema: {
                id: 'ServerLogs',
                component: ServerLogs,
            },
        },
    },
    user_management: {
        icon: 'fa-users',
        sectionTitle: t('admin.sidebar.userManagement'),
        sectionTitleDefault: 'User Management',
        system_user_detail: {
            url: 'user_management/user/:user_id',
            schema: {
                id: 'SystemUserDetail',
                component: SystemUserDetail,
            },
        },
        system_users: {
            url: 'user_management/users',
            title: t('admin.sidebar.users'),
            title_default: 'Users',
            searchableStrings: [
                ['admin.system_users.title', {siteName: ''}],
            ],
            schema: {
                id: 'SystemUsers',
                component: SystemUsers,
            },
        },
        group_detail: {
            url: 'user_management/groups/:group_id',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('LDAPGroups')),
            ),
            schema: {
                id: 'GroupDetail',
                component: GroupDetails,
            },
        },
        groups: {
            url: 'user_management/groups',
            title: t('admin.sidebar.groups'),
            title_default: 'Groups',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('LDAPGroups')),
            ),
            schema: {
                id: 'Groups',
                component: GroupSettings,
            },
        },
        team_detail: {
            url: 'user_management/teams/:team_id',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('LDAPGroups')),
            ),
            schema: {
                id: 'TeamDetail',
                component: TeamDetails,
            },
        },
        teams: {
            url: 'user_management/teams',
            title: t('admin.sidebar.teams'),
            title_default: 'Teams',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('LDAPGroups')),
            ),
            schema: {
                id: 'Teams',
                component: TeamSettings,
            },
        },
        channel_detail: {
            url: 'user_management/channels/:channel_id',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('LDAPGroups')),
            ),
            schema: {
                id: 'ChannelDetail',
                component: ChannelDetails,
            },
        },
        channel: {
            url: 'user_management/channels',
            title: t('admin.sidebar.channels'),
            title_default: 'Channels',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('LDAPGroups')),
            ),
            schema: {
                id: 'Channels',
                component: ChannelSettings,
            },
        },
        systemScheme: {
            url: 'user_management/permissions/system_scheme',
            isHidden: it.isnt(it.licensed),
            schema: {
                id: 'PermissionSystemScheme',
                component: PermissionSystemSchemeSettings,
            },
        },
        teamSchemeDetail: {
            url: 'user_management/permissions/team_override_scheme/:scheme_id',
            isHidden: it.either(
                it.isnt(it.licensed),
                it.isnt(it.licensedForFeature('CustomPermissionsSchemes')),
            ),
            schema: {
                id: 'PermissionSystemScheme',
                component: PermissionTeamSchemeSettings,
            },
        },
        teamScheme: {
            url: 'user_management/permissions/team_override_scheme',
            isHidden: it.either(
                it.isnt(it.licensed),
                it.isnt(it.licensedForFeature('CustomPermissionsSchemes')),
            ),
            schema: {
                id: 'PermissionSystemScheme',
                component: PermissionTeamSchemeSettings,
            },
        },
        permissions: {
            url: 'user_management/permissions/',
            title: t('admin.sidebar.permissions'),
            title_default: 'Permissions',
            isHidden: it.isnt(it.licensed),
            searchableStrings: [
                'admin.permissions.documentationLinkText',
                'admin.permissions.teamOverrideSchemesNoSchemes',
                'admin.permissions.loadMoreSchemes',
                'admin.permissions.introBanner',
                'admin.permissions.systemSchemeBannerTitle',
                'admin.permissions.systemSchemeBannerText',
                'admin.permissions.systemSchemeBannerButton',
                'admin.permissions.teamOverrideSchemesTitle',
                'admin.permissions.teamOverrideSchemesBannerText',
                'admin.permissions.teamOverrideSchemesNewButton',
            ],
            schema: {
                id: 'PermissionSchemes',
                component: PermissionSchemesSettings,
            },
        },
    },
    environment: {
        icon: 'fa-server',
        sectionTitle: t('admin.sidebar.environment'),
        sectionTitleDefault: 'Environment',
        web_server: {
            url: 'environment/web_server',
            title: t('admin.sidebar.webServer'),
            title_default: 'Web Server',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'ServiceSettings',
                name: t('admin.environment.webServer'),
                name_default: 'Web Server',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BANNER,
                        label: t('admin.rate.noteDescription'),
                        label_default: 'Changing properties in this section will require a server restart before taking effect.',
                        banner_type: 'info',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.SiteURL',
                        label: t('admin.service.siteURL'),
                        label_default: 'Site URL:',
                        help_text: t('admin.service.siteURLDescription'),
                        help_text_default: 'The URL that users will use to access Mattermost. Standard ports, such as 80 and 443, can be omitted, but non-standard ports are required. For example: http://example.com:8065. This setting is required.\n \nMattermost may be hosted at a subpath. For example: http://example.com:8065/company/mattermost. A restart is required before the server will work correctly.',
                        help_text_markdown: true,
                        placeholder: t('admin.service.siteURLExample'),
                        placeholder_default: 'E.g.: "http://example.com:8065"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        key: 'TestSiteURL',
                        action: testSiteURL,
                        label: t('admin.service.testSiteURL'),
                        label_default: 'Test Live URL',
                        loading: t('admin.service.testSiteURLTesting'),
                        loading_default: 'Testing...',
                        error_message: t('admin.service.testSiteURLFail'),
                        error_message_default: 'Test unsuccessful: {error}',
                        success_message: t('admin.service.testSiteURLSuccess'),
                        success_message_default: 'Test successful. This is a valid URL.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.ListenAddress',
                        label: t('admin.service.listenAddress'),
                        label_default: 'Listen Address:',
                        placeholder: t('admin.service.listenExample'),
                        placeholder_default: 'E.g.: ":8065"',
                        help_text: t('admin.service.listenDescription'),
                        help_text_default: 'The address and port to which to bind and listen. Specifying ":8065" will bind to all network interfaces. Specifying "127.0.0.1:8065" will only bind to the network interface having that IP address. If you choose a port of a lower level (called "system ports" or "well-known ports", in the range of 0-1023), you must have permissions to bind to that port. On Linux you can use: "sudo setcap cap_net_bind_service=+ep ./bin/mattermost" to allow Mattermost to bind to well-known ports.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.Forward80To443',
                        label: t('admin.service.forward80To443'),
                        label_default: 'Forward port 80 to 443:',
                        help_text: t('admin.service.forward80To443Description'),
                        help_text_default: 'Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server.',
                        disabled_help_text: t('admin.service.forward80To443Description.disabled'),
                        disabled_help_text_default: 'Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server.\n \nThis setting cannot be enabled until your server is [listening](#ListenAddress) on port 443.',
                        disabled_help_text_markdown: true,
                        isDisabled: it.isnt(it.stateMatches('ServiceSettings.ListenAddress', /:443$/)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'ServiceSettings.ConnectionSecurity',
                        label: t('admin.connectionSecurityTitle'),
                        label_default: 'Connection Security:',
                        help_text: DefinitionConstants.CONNECTION_SECURITY_HELP_TEXT_WEBSERVER,
                        options: [
                            {
                                value: '',
                                display_name: t('admin.connectionSecurityNone'),
                                display_name_default: 'None',
                            },
                            {
                                value: 'TLS',
                                display_name: t('admin.connectionSecurityTls'),
                                display_name_default: 'TLS (Recommended)',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.TLSCertFile',
                        label: t('admin.service.tlsCertFile'),
                        label_default: 'TLS Certificate File:',
                        help_text: t('admin.service.tlsCertFileDescription'),
                        help_text_default: 'The certificate file to use.',
                        isDisabled: it.stateIsTrue('ServiceSettings.UseLetsEncrypt'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.TLSKeyFile',
                        label: t('admin.service.tlsKeyFile'),
                        label_default: 'TLS Key File:',
                        help_text: t('admin.service.tlsKeyFileDescription'),
                        help_text_default: 'The private key file to use.',
                        isDisabled: it.stateIsTrue('ServiceSettings.UseLetsEncrypt'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.UseLetsEncrypt',
                        label: t('admin.service.useLetsEncrypt'),
                        label_default: 'Use Let\'s Encrypt:',
                        help_text: t('admin.service.useLetsEncryptDescription'),
                        help_text_default: 'Enable the automatic retrieval of certificates from Let\'s Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.',
                        disabled_help_text: t('admin.service.useLetsEncryptDescription.disabled'),
                        disabled_help_text_default: 'Enable the automatic retrieval of certificates from Let\'s Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.\n \nThis setting cannot be enabled unless the [Forward port 80 to 443](#Forward80To443) setting is set to true.',
                        disabled_help_text_markdown: true,
                        isDisabled: it.stateIsFalse('ServiceSettings.Forward80To443'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.LetsEncryptCertificateCacheFile',
                        label: t('admin.service.letsEncryptCertificateCacheFile'),
                        label_default: 'Let\'s Encrypt Certificate Cache File:',
                        help_text: t('admin.service.letsEncryptCertificateCacheFileDescription'),
                        help_text_default: 'Certificates retrieved and other data about the Let\'s Encrypt service will be stored in this file.',
                        isDisabled: it.stateIsFalse('ServiceSettings.UseLetsEncrypt'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'ServiceSettings.ReadTimeout',
                        label: t('admin.service.readTimeout'),
                        label_default: 'Read Timeout:',
                        help_text: t('admin.service.readTimeoutDescription'),
                        help_text_default: 'Maximum time allowed from when the connection is accepted to when the request body is fully read.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'ServiceSettings.WriteTimeout',
                        label: t('admin.service.writeTimeout'),
                        label_default: 'Write Timeout:',
                        help_text: t('admin.service.writeTimeoutDescription'),
                        help_text_default: 'If using HTTP (insecure), this is the maximum time allowed from the end of reading the request headers until the response is written. If using HTTPS, it is the total time from when the connection is accepted until the response is written.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'ServiceSettings.WebserverMode',
                        label: t('admin.webserverModeTitle'),
                        label_default: 'Webserver Mode:',
                        help_text: DefinitionConstants.WEBSERVER_MODE_HELP_TEXT,
                        options: [
                            {
                                value: 'gzip',
                                display_name: t('admin.webserverModeGzip'),
                                display_name_default: 'gzip',
                            },
                            {
                                value: 'uncompressed',
                                display_name: t('admin.webserverModeUncompressed'),
                                display_name_default: 'Uncompressed',
                            },
                            {
                                value: 'disabled',
                                display_name: t('admin.webserverModeDisabled'),
                                display_name_default: 'Disabled',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableInsecureOutgoingConnections',
                        label: t('admin.service.insecureTlsTitle'),
                        label_default: 'Enable Insecure Outgoing Connections: ',
                        help_text: t('admin.service.insecureTlsDesc'),
                        help_text_default: 'When true, any outgoing HTTPS requests will accept unverified, self-signed certificates. For example, outgoing webhooks to a server with a self-signed TLS certificate, using any domain, will be allowed. Note that this makes these connections susceptible to man-in-the-middle attacks.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        action: reloadConfig,
                        key: 'ReloadConfigButton',
                        label: t('admin.reload.button'),
                        label_default: 'Reload Configuration From Disk',
                        help_text: t('admin.reload.reloadDescription'),
                        help_text_default: 'Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating "config.json" to the new desired configuration and using the {featureName} feature to load the new settings while the server is running. The administrator should then use the {recycleDatabaseConnections} feature to recycle the database connections based on the new settings.',
                        help_text_values: {
                            featureName: (
                                <b>
                                    <FormattedMessage
                                        id='admin.reload.reloadDescription.featureName'
                                        defaultMessage='Reload Configuration from Disk'
                                    />
                                </b>
                            ),
                            recycleDatabaseConnections: (
                                <a href='../environment/database'>
                                    <b>
                                        <FormattedMessage
                                            id='admin.reload.reloadDescription.recycleDatabaseConnections'
                                            defaultMessage='Environment > Database > Recycle Database Connections'
                                        />
                                    </b>
                                </a>
                            ),
                        },
                        error_message: t('admin.reload.reloadFail'),
                        error_message_default: 'Reload unsuccessful: {error}',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        key: 'PurgeButton',
                        action: invalidateAllCaches,
                        label: t('admin.purge.button'),
                        label_default: 'Purge All Caches',
                        help_text: t('admin.purge.purgeDescription'),
                        help_text_default: 'This will purge all the in-memory caches for things like sessions, accounts, channels, etc. Deployments using High Availability will attempt to purge all the servers in the cluster.  Purging the caches may adversely impact performance.',
                        error_message: t('admin.purge.purgeFail'),
                        error_message_default: 'Purging unsuccessful: {error}',
                    },
                ],
            },
        },
        database: {
            url: 'environment/database',
            title: t('admin.sidebar.database'),
            title_default: 'Database',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            searchableStrings: [
                'admin.database.title',
                ['admin.recycle.recycleDescription', {featureName: '', reloadConfiguration: ''}],
                'admin.recycle.recycleDescription.featureName',
                'admin.recycle.recycleDescription.reloadConfiguration',
                'admin.recycle.button',
                'admin.sql.noteDescription',
                'admin.sql.disableDatabaseSearchTitle',
                'admin.sql.disableDatabaseSearchDescription',
                'admin.sql.driverName',
                'admin.sql.driverNameDescription',
                'admin.sql.dataSource',
                'admin.sql.dataSourceDescription',
                'admin.sql.maxConnectionsTitle',
                'admin.sql.maxConnectionsDescription',
                'admin.sql.maxOpenTitle',
                'admin.sql.maxOpenDescription',
                'admin.sql.queryTimeoutTitle',
                'admin.sql.queryTimeoutDescription',
                'admin.sql.connMaxLifetimeTitle',
                'admin.sql.connMaxLifetimeDescription',
                'admin.sql.traceTitle',
                'admin.sql.traceDescription',
            ],
            schema: {
                id: 'DatabaseSettings',
                component: DatabaseSettings,
            },
        },
        elasticsearch: {
            url: 'environment/elasticsearch',
            title: t('admin.sidebar.elasticsearch'),
            title_default: 'Elasticsearch',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('Elasticsearch')),
                it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            ),
            searchableStrings: [
                'admin.elasticsearch.title',
                'admin.elasticsearch.enableIndexingTitle',
                ['admin.elasticsearch.enableIndexingDescription', {documentationLink: ''}],
                'admin.elasticsearch.enableIndexingDescription.documentationLinkText',
                'admin.elasticsearch.connectionUrlTitle',
                ['admin.elasticsearch.connectionUrlDescription', {documentationLink: ''}],
                'admin.elasticsearch.connectionUrlExample.documentationLinkText',
                'admin.elasticsearch.skipTLSVerificationTitle',
                'admin.elasticsearch.skipTLSVerificationDescription',
                'admin.elasticsearch.usernameTitle',
                'admin.elasticsearch.usernameDescription',
                'admin.elasticsearch.passwordTitle',
                'admin.elasticsearch.passwordDescription',
                'admin.elasticsearch.sniffTitle',
                'admin.elasticsearch.sniffDescription',
                'admin.elasticsearch.testHelpText',
                'admin.elasticsearch.elasticsearch_test_button',
                'admin.elasticsearch.bulkIndexingTitle',
                'admin.elasticsearch.createJob.help',
                'admin.elasticsearch.purgeIndexesHelpText',
                'admin.elasticsearch.purgeIndexesButton',
                'admin.elasticsearch.purgeIndexesButton.label',
                'admin.elasticsearch.enableSearchingTitle',
                'admin.elasticsearch.enableSearchingDescription',
            ],
            schema: {
                id: 'ElasticSearchSettings',
                component: ElasticSearchSettings,
            },
        },
        storage: {
            url: 'environment/file_storage',
            title: t('admin.sidebar.fileStorage'),
            title_default: 'File Storage',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'FileSettings',
                name: t('admin.environment.fileStorage'),
                name_default: 'File Storage',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'FileSettings.DriverName',
                        label: t('admin.image.storeTitle'),
                        label_default: 'File Storage System:',
                        help_text: t('admin.image.storeDescription'),
                        help_text_default: 'Storage system where files and image attachments are saved.\n \nSelecting "Amazon S3" enables fields to enter your Amazon credentials and bucket details.\n \nSelecting "Local File System" enables the field to specify a local file directory.',
                        help_text_markdown: true,
                        options: [
                            {
                                value: FILE_STORAGE_DRIVER_LOCAL,
                                display_name: t('admin.image.storeLocal'),
                                display_name_default: 'Local File System',
                            },
                            {
                                value: FILE_STORAGE_DRIVER_S3,
                                display_name: t('admin.image.storeAmazonS3'),
                                display_name_default: 'Amazon S3',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.Directory',
                        label: t('admin.image.localTitle'),
                        label_default: 'Local Storage Directory:',
                        help_text: t('admin.image.localDescription'),
                        help_text_default: 'Directory to which files and images are written. If blank, defaults to ./data/.',
                        placeholder: t('admin.image.localExample'),
                        placeholder_default: 'E.g.: "./data/"',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_LOCAL)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'FileSettings.MaxFileSize',
                        label: t('admin.image.maxFileSizeTitle'),
                        label_default: 'Maximum File Size:',
                        help_text: t('admin.image.maxFileSizeDescription'),
                        help_text_default: 'Maximum file size for message attachments in megabytes. Caution: Verify server memory can support your setting choice. Large file sizes increase the risk of server crashes and failed uploads due to network interruptions.',
                        placeholder: t('admin.image.maxFileSizeExample'),
                        placeholder_default: '50',
                        onConfigLoad: (configVal) => configVal / MEBIBYTE,
                        onConfigSave: (displayVal) => displayVal * MEBIBYTE,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.AmazonS3Bucket',
                        label: t('admin.image.amazonS3BucketTitle'),
                        label_default: 'Amazon S3 Bucket:',
                        help_text: t('admin.image.amazonS3BucketDescription'),
                        help_text_default: 'Name you selected for your S3 bucket in AWS.',
                        placeholder: t('admin.image.amazonS3BucketExample'),
                        placeholder_default: 'E.g.: "mattermost-media"',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.AmazonSPathPrefix',
                        label: t('admin.image.amazonS3PathPrefixTitle'),
                        label_default: 'Amazon S3 Path Prefix:',
                        help_text: t('admin.image.amazonS3PathPrefixDescription'),
                        help_text_default: 'Prefix you selected for your S3 bucket in AWS.',
                        placeholder: t('admin.image.amazonS3PathPrefixExample'),
                        placeholder_default: 'E.g.: "subdir1/" or you can leave it .',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.AmazonS3Region',
                        label: t('admin.image.amazonS3RegionTitle'),
                        label_default: 'Amazon S3 Region:',
                        help_text: t('admin.image.amazonS3RegionDescription'),
                        help_text_default: 'AWS region you selected when creating your S3 bucket. If no region is set, Mattermost attempts to get the appropriate region from AWS, or sets it to "us-east-1" if none found.',
                        placeholder: t('admin.image.amazonS3RegionExample'),
                        placeholder_default: 'E.g.: "us-east-1"',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.AmazonS3AccessKeyId',
                        label: t('admin.image.amazonS3IdTitle'),
                        label_default: 'Amazon S3 Access Key ID:',
                        help_text: t('admin.image.amazonS3IdDescription'),
                        help_text_markdown: true,
                        help_text_default: '(Optional) Only required if you do not want to authenticate to S3 using an [IAM role](!https://about.mattermost.com/default-iam-role). Enter the Access Key ID provided by your Amazon EC2 administrator.',
                        placeholder: t('admin.image.amazonS3IdExample'),
                        placeholder_default: 'E.g.: "AKIADTOVBGERKLCBV"',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.AmazonS3Endpoint',
                        label: t('admin.image.amazonS3EndpointTitle'),
                        label_default: 'Amazon S3 Endpoint:',
                        help_text: t('admin.image.amazonS3EndpointDescription'),
                        help_text_default: 'Hostname of your S3 Compatible Storage provider. Defaults to "s3.amazonaws.com".',
                        placeholder: t('admin.image.amazonS3EndpointExample'),
                        placeholder_default: 'E.g.: "s3.amazonaws.com"',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'FileSettings.AmazonS3SecretAccessKey',
                        label: t('admin.image.amazonS3SecretTitle'),
                        label_default: 'Amazon S3 Secret Access Key:',
                        help_text: t('admin.image.amazonS3SecretDescription'),
                        help_text_default: '(Optional) The secret access key associated with your Amazon S3 Access Key ID.',
                        placeholder: t('admin.image.amazonS3SecretExample'),
                        placeholder_default: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.AmazonS3SSL',
                        label: t('admin.image.amazonS3SSLTitle'),
                        label_default: 'Enable Secure Amazon S3 Connections:',
                        help_text: t('admin.image.amazonS3SSLDescription'),
                        help_text_default: 'When false, allow insecure connections to Amazon S3. Defaults to secure connections only.',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.AmazonS3SSE',
                        label: t('admin.image.amazonS3SSETitle'),
                        label_default: 'Enable Server-Side Encryption for Amazon S3:',
                        help_text: t('admin.image.amazonS3SSEDescription'),
                        help_text_markdown: true,
                        help_text_default: 'When true, encrypt files in Amazon S3 using server-side encryption with Amazon S3-managed keys. See [documentation](!https://about.mattermost.com/default-server-side-encryption) to learn more.',
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.AmazonS3Trace',
                        label: t('admin.image.amazonS3TraceTitle'),
                        label_default: 'Enable Amazon S3 Debugging:',
                        help_text: t('admin.image.amazonS3TraceDescription'),
                        help_text_default: '(Development Mode) When true, log additional debugging information to the system logs.',
                        isDisabled: it.isnt(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        action: testS3Connection,
                        key: 'TestS3Connection',
                        label: t('admin.s3.connectionS3Test'),
                        label_default: 'Test Connection',
                        loading: t('admin.s3.testing'),
                        loading_default: 'Testing...',
                        error_message: t('admin.s3.s3Fail'),
                        error_message_default: 'Connection unsuccessful: {error}',
                        success_message: t('admin.s3.s3Success'),
                        success_message_default: 'Connection was successful',
                    },
                ],
            },
        },
        image_proxy: {
            url: 'environment/image_proxy',
            title: t('admin.sidebar.imageProxy'),
            title_default: 'Image Proxy',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'ImageProxy',
                name: t('admin.environment.imageProxy'),
                name_default: 'Image Proxy',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ImageProxySettings.Enable',
                        label: t('admin.image.enableProxy'),
                        label_default: 'Enable Image Proxy:',
                        help_text: t('admin.image.enableProxyDescription'),
                        help_text_default: 'When true, enables an image proxy for loading all Markdown images.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'ImageProxySettings.ImageProxyType',
                        label: t('admin.image.proxyType'),
                        label_default: 'Image Proxy Type:',
                        help_text: t('admin.image.proxyTypeDescription'),
                        help_text_default: 'Configure an image proxy to load all Markdown images through a proxy. The image proxy prevents users from making insecure image requests, provides caching for increased performance, and automates image adjustments such as resizing. See [documentation](!https://about.mattermost.com/default-image-proxy-documentation) to learn more.',
                        help_text_markdown: true,
                        options: [
                            {
                                value: 'atmos/camo',
                                display_name: t('atmos/camo'),
                                display_name_default: 'atmos/camo',
                            },
                            {
                                value: 'local',
                                display_name: t('local'),
                                display_name_default: 'local',
                            },
                        ],
                        isDisabled: it.stateIsFalse('ImageProxySettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ImageProxySettings.RemoteImageProxyURL',
                        label: t('admin.image.proxyURL'),
                        label_default: 'Remote Image Proxy URL:',
                        help_text: t('admin.image.proxyURLDescription'),
                        help_text_default: 'URL of your remote image proxy server.',
                        isDisabled: it.either(
                            it.stateIsFalse('ImageProxySettings.Enable'),
                            it.stateEquals('ImageProxySettings.ImageProxyType', 'local'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ImageProxySettings.RemoteImageProxyOptions',
                        label: t('admin.image.proxyOptions'),
                        label_default: 'Remote Image Proxy Options:',
                        help_text: t('admin.image.proxyOptionsDescription'),
                        help_text_default: 'Additional options such as the URL signing key. Refer to your image proxy documentation to learn more about what options are supported.',
                        isDisabled: it.either(
                            it.stateIsFalse('ImageProxySettings.Enable'),
                            it.stateEquals('ImageProxySettings.ImageProxyType', 'local'),
                        ),
                    },
                ],
            },
        },
        smtp: {
            url: 'environment/smtp',
            title: t('admin.sidebar.smtp'),
            title_default: 'SMTP',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'SMTP',
                name: t('admin.environment.smtp'),
                name_default: 'SMTP',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.SMTPServer',
                        label: t('admin.environment.smtp.smtpServer.title'),
                        label_default: 'SMTP Server:',
                        placeholder: t('admin.environment.smtp.smtpServer.placeholder'),
                        placeholder_default: 'Ex: "smtp.yourcompany.com", "email-smtp.us-east-1.amazonaws.com"',
                        help_text: t('admin.environment.smtp.smtpServer.description'),
                        help_text_default: 'Location of SMTP email server.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.SMTPPort',
                        label: t('admin.environment.smtp.smtpPort.title'),
                        label_default: 'SMTP Server Port:',
                        placeholder: t('admin.environment.smtp.smtpPort.placeholder'),
                        placeholder_default: 'Ex: "25", "465", "587"',
                        help_text: t('admin.environment.smtp.smtpPort.description'),
                        help_text_default: 'Port of SMTP email server.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.EnableSMTPAuth',
                        label: t('admin.environment.smtp.smtpAuth.title'),
                        label_default: 'Enable SMTP Authentication:',
                        help_text: t('admin.environment.smtp.smtpAuth.description'),
                        help_text_default: 'When true, SMTP Authentication is enabled.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.SMTPUsername',
                        label: t('admin.environment.smtp.smtpUsername.title'),
                        label_default: 'SMTP Server Username:',
                        placeholder: t('admin.environment.smtp.smtpUsername.placeholder'),
                        placeholder_default: 'Ex: "admin@yourcompany.com", "AKIADTOVBGERKLCBV"',
                        help_text: t('admin.environment.smtp.smtpUsername.description'),
                        help_text_default: 'Obtain this credential from administrator setting up your email server.',
                        isDisabled: it.stateIsFalse('EmailSettings.EnableSMTPAuth'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.SMTPPassword',
                        label: t('admin.environment.smtp.smtpPassword.title'),
                        label_default: 'SMTP Server Password:',
                        placeholder: t('admin.environment.smtp.smtpPassword.placeholder'),
                        placeholder_default: 'Ex: "yourpassword", "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"',
                        help_text: t('admin.environment.smtp.smtpPassword.description'),
                        help_text_default: 'Obtain this credential from administrator setting up your email server.',
                        isDisabled: it.stateIsFalse('EmailSettings.EnableSMTPAuth'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'EmailSettings.ConnectionSecurity',
                        label: t('admin.environment.smtp.connectionSecurity.title'),
                        label_default: 'Connection Security:',
                        help_text: DefinitionConstants.CONNECTION_SECURITY_HELP_TEXT_EMAIL,
                        options: [
                            {
                                value: '',
                                display_name: t('admin.environment.smtp.connectionSecurity.option.none'),
                                display_name_default: 'None',
                            },
                            {
                                value: 'TLS',
                                display_name: t('admin.environment.smtp.connectionSecurity.option.tls'),
                                display_name_default: 'TLS (Recommended)',
                            },
                            {
                                value: 'STARTTLS',
                                display_name: t('admin.environment.smtp.connectionSecurity.option.starttls'),
                                display_name_default: 'STARTTLS',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        action: testSmtp,
                        key: 'TestSmtpConnection',
                        label: t('admin.environment.smtp.connectionSmtpTest'),
                        label_default: 'Test Connection',
                        loading: t('admin.environment.smtp.testing'),
                        loading_default: 'Testing...',
                        error_message: t('admin.environment.smtp.smtpFail'),
                        error_message_default: 'Connection unsuccessful: {error}',
                        success_message: t('admin.environment.smtp.smtpSuccess'),
                        success_message_default: 'No errors were reported while sending an email. Please check your inbox to make sure.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.SkipServerCertificateVerification',
                        label: t('admin.environment.smtp.skipServerCertificateVerification.title'),
                        label_default: 'Skip Server Certificate Verification:',
                        help_text: t('admin.environment.smtp.skipServerCertificateVerification.description'),
                        help_text_default: 'When true, Mattermost will not verify the email server certificate.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableSecurityFixAlert',
                        label: t('admin.environment.smtp.enableSecurityFixAlert.title'),
                        label_default: 'Enable Security Alerts:',
                        help_text: t('admin.environment.smtp.enableSecurityFixAlert.description'),
                        help_text_default: 'When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.',
                    },
                ],
            },
        },
        push_notification_server: {
            url: 'environment/push_notification_server',
            title: t('admin.sidebar.pushNotificationServer'),
            title_default: 'Push Notification Server',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            searchableStrings: [
                'admin.environment.pushNotificationServer',
                'admin.email.pushTitle',
                'admin.email.pushServerTitle',
                'admin.email.pushContentTitle',
                'admin.email.pushContentDesc',
            ],
            schema: {
                id: 'PushNotificationsSettings',
                component: PushNotificationsSettings,
            },
        },
        high_availability: {
            url: 'environment/high_availability',
            title: t('admin.sidebar.highAvailability'),
            title_default: 'High Availability',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('Cluster')),
                it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            ),
            searchableStrings: [
                'admin.advance.cluster',
                'admin.cluster.noteDescription',
                'admin.cluster.enableTitle',
                'admin.cluster.enableDescription',
                'admin.cluster.ClusterName',
                'admin.cluster.ClusterNameDesc',
                'admin.cluster.OverrideHostname',
                'admin.cluster.OverrideHostnameDesc',
                'admin.cluster.UseIpAddress',
                'admin.cluster.UseIpAddressDesc',
                'admin.cluster.UseExperimentalGossip',
                'admin.cluster.UseExperimentalGossipDesc',
                'admin.cluster.EnableExperimentalGossipEncryption',
                'admin.cluster.EnableExperimentalGossipEncryptionDesc',
                'admin.cluster.GossipPort',
                'admin.cluster.GossipPortDesc',
                'admin.cluster.StreamingPort',
                'admin.cluster.StreamingPortDesc',
            ],
            schema: {
                id: 'ClusterSettings',
                component: ClusterSettings,
            },
        },
        rate_limiting: {
            url: 'environment/rate_limiting',
            title: t('admin.sidebar.rateLimiting'),
            title_default: 'Rate Limiting',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'ServiceSettings',
                name: t('admin.rate.title'),
                name_default: 'Rate Limiting',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BANNER,
                        label: t('admin.rate.noteDescription'),
                        label_default: 'Changing properties other than Site URL in this section will require a server restart before taking effect.',
                        banner_type: 'info',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'RateLimitSettings.Enable',
                        label: t('admin.rate.enableLimiterTitle'),
                        label_default: 'Enable Rate Limiting:',
                        help_text: t('admin.rate.enableLimiterDescription'),
                        help_text_default: 'When true, APIs are throttled at rates specified below.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'RateLimitSettings.PerSec',
                        label: t('admin.rate.queriesTitle'),
                        label_default: 'Maximum Queries per Second:',
                        placeholder: t('admin.rate.queriesExample'),
                        placeholder_default: 'E.g.: "10"',
                        help_text: t('admin.rate.queriesDescription'),
                        help_text_default: 'Throttles API at this number of requests per second.',
                        isDisabled: it.stateEquals('RateLimitSettings.Enable', false),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'RateLimitSettings.MaxBurst',
                        label: t('admin.rate.maxBurst'),
                        label_default: 'Maximum Burst Size:',
                        placeholder: t('admin.rate.maxBurstExample'),
                        placeholder_default: 'E.g.: "100"',
                        help_text: t('admin.rate.maxBurstDescription'),
                        help_text_default: 'Maximum number of requests allowed beyond the per second query limit.',
                        isDisabled: it.stateEquals('RateLimitSettings.Enable', false),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'RateLimitSettings.MemoryStoreSize',
                        label: t('admin.rate.memoryTitle'),
                        label_default: 'Memory Store Size:',
                        placeholder: t('admin.rate.memoryExample'),
                        placeholder_default: 'E.g.: "10000"',
                        help_text: t('admin.rate.memoryDescription'),
                        help_text_default: 'Maximum number of users sessions connected to the system as determined by "Vary rate limit by remote address" and "Vary rate limit by HTTP header".',
                        isDisabled: it.stateEquals('RateLimitSettings.Enable', false),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'RateLimitSettings.VaryByRemoteAddr',
                        label: t('admin.rate.remoteTitle'),
                        label_default: 'Vary rate limit by remote address:',
                        help_text: t('admin.rate.remoteDescription'),
                        help_text_default: 'When true, rate limit API access by IP address.',
                        isDisabled: it.stateEquals('RateLimitSettings.Enable', false),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'RateLimitSettings.VaryByUser',
                        label: t('admin.rate.varyByUser'),
                        label_default: 'Vary rate limit by user:',
                        help_text: t('admin.rate.varyByUserDescription'),
                        help_text_default: 'When true, rate limit API access by user athentication token.',
                        isDisabled: it.stateEquals('RateLimitSettings.Enable', false),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'RateLimitSettings.VaryByHeader',
                        label: t('admin.rate.httpHeaderTitle'),
                        label_default: 'Vary rate limit by HTTP header:',
                        placeholder: t('admin.rate.httpHeaderExample'),
                        placeholder_default: 'E.g.: "X-Real-IP", "X-Forwarded-For"',
                        help_text: t('admin.rate.httpHeaderDescription'),
                        help_text_default: 'When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").',
                        isDisabled: it.either(
                            it.stateEquals('RateLimitSettings.Enable', false),
                            it.stateEquals('RateLimitSettings.VaryByRemoteAddr', true),
                        ),
                    },
                ],
            },
        },
        logging: {
            url: 'environment/logging',
            title: t('admin.sidebar.logging'),
            title_default: 'Logging',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'LogSettings',
                name: t('admin.general.log'),
                name_default: 'Logging',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LogSettings.EnableConsole',
                        label: t('admin.log.consoleTitle'),
                        label_default: 'Output logs to console: ',
                        help_text: t('admin.log.consoleDescription'),
                        help_text_default: 'Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option.  If true, server writes messages to the standard output stream (stdout). Changing this setting requires a server restart before taking effect.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'LogSettings.ConsoleLevel',
                        label: t('admin.log.levelTitle'),
                        label_default: 'Console Log Level:',
                        help_text: t('admin.log.levelDescription'),
                        help_text_default: 'This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.',
                        options: DefinitionConstants.LOG_LEVEL_OPTIONS,
                        isDisabled: it.stateIsFalse('LogSettings.EnableConsole'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LogSettings.ConsoleJson',
                        label: t('admin.log.consoleJsonTitle'),
                        label_default: 'Output console logs as JSON:',
                        help_text: t('admin.log.jsonDescription'),
                        help_text_default: 'When true, logged events are written in a machine readable JSON format. Otherwise they are printed as plain text. Changing this setting requires a server restart before taking effect.',
                        isDisabled: it.stateIsFalse('LogSettings.EnableConsole'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LogSettings.EnableFile',
                        label: t('admin.log.fileTitle'),
                        label_default: 'Output logs to file: ',
                        help_text: t('admin.log.fileDescription'),
                        help_text_default: 'Typically set to true in production. When true, logged events are written to the mattermost.log file in the directory specified in the File Log Directory field. The logs are rotated at 10,000 lines and archived to a file in the same directory, and given a name with a datestamp and serial number. For example, mattermost.2017-03-31.001. Changing this setting requires a server restart before taking effect.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'LogSettings.FileLevel',
                        label: t('admin.log.fileLevelTitle'),
                        label_default: 'File Log Level:',
                        help_text: t('admin.log.fileLevelDescription'),
                        help_text_default: 'This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.',
                        options: DefinitionConstants.LOG_LEVEL_OPTIONS,
                        isDisabled: it.stateIsFalse('LogSettings.EnableFile'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LogSettings.FileJson',
                        label: t('admin.log.fileJsonTitle'),
                        label_default: 'Output file logs as JSON:',
                        help_text: t('admin.log.jsonDescription'),
                        help_text_default: 'When true, logged events are written in a machine readable JSON format. Otherwise they are printed as plain text. Changing this setting requires a server restart before taking effect.',
                        isDisabled: it.stateIsFalse('LogSettings.EnableFile'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LogSettings.FileLocation',
                        label: t('admin.log.locationTitle'),
                        label_default: 'File Log Directory:',
                        help_text: t('admin.log.locationDescription'),
                        help_text_default: 'The location of the log files. If blank, they are stored in the ./logs directory. The path that you set must exist and Mattermost must have write permissions in it. Changing this setting requires a server restart before taking effect.',
                        placeholder: t('admin.log.locationPlaceholder'),
                        placeholder_default: 'Enter your file location',
                        isDisabled: it.stateIsFalse('LogSettings.EnableFile'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LogSettings.EnableWebhookDebugging',
                        label: t('admin.log.enableWebhookDebugging'),
                        label_default: 'Enable Webhook Debugging:',
                        help_text: t('admin.log.enableWebhookDebuggingDescription'),
                        help_text_default: 'When true, sends webhook debug messages to the server logs. To also output the request body of incoming webhooks, set {boldedLogLevel} to "DEBUG".',
                        help_text_values: {
                            boldedLogLevel: (
                                <strong>
                                    <FormattedMessage
                                        id='admin.log.logLevel'
                                        defaultMessage='Log Level'
                                    />
                                </strong>
                            ),
                        },
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LogSettings.EnableDiagnostics',
                        label: t('admin.log.enableDiagnostics'),
                        label_default: 'Enable Diagnostics and Error Reporting:',
                        help_text: t('admin.log.enableDiagnosticsDescription'),
                        help_text_default: 'Enable this feature to improve the quality and performance of Mattermost by sending error reporting and diagnostic information to Mattermost, Inc. Read our [privacy policy](!https://about.mattermost.com/default-privacy-policy/) to learn more.',
                        help_text_markdown: true,
                        onConfigSave: (displayVal, previousVal) => {
                            if (previousVal && previousVal !== displayVal) {
                                trackEvent('ui', 'diagnostics_disabled');
                            }
                            return displayVal;
                        },
                    },
                ],
            },
        },
        session_lengths: {
            url: 'environment/session_lengths',
            title: t('admin.sidebar.sessionLengths'),
            title_default: 'Session Lengths',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            searchableStrings: [
                'admin.sessionLengths.title',
                'admin.service.webSessionDaysDesc.extendLength',
                'admin.service.mobileSessionDaysDesc.extendLength',
                'admin.service.ssoSessionDaysDesc.extendLength',
                'admin.service.webSessionDaysDesc',
                'admin.service.mobileSessionDaysDesc',
                'admin.service.ssoSessionDaysDesc',
                'admin.service.sessionIdleTimeout',
                'admin.service.sessionIdleTimeoutDesc',
                'admin.service.extendSessionLengthActivity.label',
                'admin.service.extendSessionLengthActivity.helpText',
                'admin.service.webSessionDays',
                'admin.service.sessionDaysEx',
                'admin.service.mobileSessionDays',
                'admin.service.ssoSessionDays',
                'admin.service.sessionCache',
                'admin.service.sessionCacheDesc',
            ],
            schema: {
                id: 'SessionLengths',
                component: SessionLengthSettings,
            },
        },
        metrics: {
            url: 'environment/performance_monitoring',
            title: t('admin.sidebar.metrics'),
            title_default: 'Performance Monitoring',
            isHidden: it.either(
                it.isnt(it.licensedForFeature('Metrics')),
                it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            ),
            schema: {
                id: 'MetricsSettings',
                name: t('admin.advance.metrics'),
                name_default: 'Performance Monitoring',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'MetricsSettings.Enable',
                        label: t('admin.metrics.enableTitle'),
                        label_default: 'Enable Performance Monitoring:',
                        help_text: t('admin.metrics.enableDescription'),
                        help_text_default: 'When true, Mattermost will enable performance monitoring collection and profiling. Please see [documentation](!http://docs.mattermost.com/deployment/metrics.html) to learn more about configuring performance monitoring for Mattermost.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'MetricsSettings.ListenAddress',
                        label: t('admin.metrics.listenAddressTitle'),
                        label_default: 'Listen Address:',
                        placeholder: t('admin.metrics.listenAddressEx'),
                        placeholder_default: 'E.g.: ":8067"',
                        help_text: t('admin.metrics.listenAddressDesc'),
                        help_text_default: 'The address the server will listen on to expose performance metrics.',
                    },
                ],
            },
        },
        developer: {
            url: 'environment/developer',
            title: t('admin.sidebar.developer'),
            title_default: 'Developer',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'ServiceSettings',
                name: t('admin.developer.title'),
                name_default: 'Developer Settings',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableTesting',
                        label: t('admin.service.testingTitle'),
                        label_default: 'Enable Testing Commands:',
                        help_text: t('admin.service.testingDescription'),
                        help_text_default: 'When true, /test slash command is enabled to load test accounts, data and text formatting. Changing this requires a server restart before taking effect.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableDeveloper',
                        label: t('admin.service.developerTitle'),
                        label_default: 'Enable Developer Mode: ',
                        help_text: t('admin.service.developerDesc'),
                        help_text_default: 'When true, JavaScript errors are shown in a purple bar at the top of the user interface. Not recommended for use in production.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.AllowedUntrustedInternalConnections',
                        label: t('admin.service.internalConnectionsTitle'),
                        label_default: 'Allow untrusted internal connections to: ',
                        placeholder: t('admin.service.internalConnectionsEx'),
                        placeholder_default: 'webhooks.internal.example.com 127.0.0.1 10.0.16.0/28',
                        help_text: t('admin.service.internalConnectionsDesc'),
                        help_text_default: 'A whitelist of local network addresses that can be requested by the Mattermost server on behalf of a client. Care should be used when configuring this setting to prevent unintended access to your local network. See [documentation](!https://mattermost.com/pl/default-allow-untrusted-internal-connections) to learn more.',
                        help_text_markdown: true,
                    },
                ],
            },
        },
    },
    site: {
        icon: 'fa-cogs',
        sectionTitle: t('admin.sidebar.site'),
        sectionTitleDefault: 'Site Configuration',
        customization: {
            url: 'site_config/customization',
            title: t('admin.sidebar.customization'),
            title_default: 'Customization',
            schema: {
                id: 'Customization',
                name: t('admin.site.customization'),
                name_default: 'Customization',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'TeamSettings.SiteName',
                        label: t('admin.team.siteNameTitle'),
                        label_default: 'Site Name:',
                        help_text: t('admin.team.siteNameDescription'),
                        help_text_default: 'Name of service shown in login screens and UI. When not specified, it defaults to "Mattermost".',
                        placeholder: t('admin.team.siteNameExample'),
                        placeholder_default: 'E.g.: "Mattermost"',
                        max_length: Constants.MAX_SITENAME_LENGTH,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'TeamSettings.CustomDescriptionText',
                        label: t('admin.team.brandDescriptionTitle'),
                        label_default: 'Site Description: ',
                        help_text: t('admin.team.brandDescriptionHelp'),
                        help_text_default: 'Description of service shown in login screens and UI. When not specified, "All team communication in one place, searchable and accessible anywhere" is displayed.',
                        placeholder: t('web.root.signup_info'),
                        placeholder_default: 'All team communication in one place, searchable and accessible anywhere',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.EnableCustomBrand',
                        label: t('admin.team.brandTitle'),
                        label_default: 'Enable Custom Branding: ',
                        help_text: t('admin.team.brandDesc'),
                        help_text_default: 'Enable custom branding to show an image of your choice, uploaded below, and some help text, written below, on the login page.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_CUSTOM,
                        component: BrandImageSetting,
                        isDisabled: it.stateIsFalse('TeamSettings.EnableCustomBrand'),
                        key: 'CustomBrandImage',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_LONG_TEXT,
                        key: 'TeamSettings.CustomBrandText',
                        label: t('admin.team.brandTextTitle'),
                        label_default: 'Custom Brand Text:',
                        help_text: t('admin.team.brandTextDescription'),
                        help_text_default: 'Text that will appear below your custom brand image on your login screen. Supports Markdown-formatted text. Maximum 500 characters allowed.',
                        isDisabled: it.stateIsFalse('TeamSettings.EnableCustomBrand'),
                        max_length: Constants.MAX_CUSTOM_BRAND_TEXT_LENGTH,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SupportSettings.EnableAskCommunityLink',
                        label: t('admin.support.enableAskCommunityTitle'),
                        label_default: 'Enable Ask Community Link:',
                        help_text: t('admin.support.enableAskCommunityDesc'),
                        help_text_default: 'When true, "Ask the community" link appears on the Mattermost user interface and Main Menu, which allows users to join the Mattermost Community to ask questions and help others troubleshoot issues. When false, the link is hidden from users.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SupportSettings.HelpLink',
                        label: t('admin.support.helpTitle'),
                        label_default: 'Help Link:',
                        help_text: t('admin.support.helpDesc'),
                        help_text_default: 'The URL for the Help link on the Mattermost login page, sign-up pages, and Main Menu. If this field is empty, the Help link is hidden from users.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SupportSettings.SupportEmail',
                        label: t('admin.support.emailTitle'),
                        label_default: 'Support Email:',
                        help_text: t('admin.support.emailHelp'),
                        help_text_default: 'Email address displayed on email notifications and during tutorial for end users to ask support questions.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SupportSettings.TermsOfServiceLink',
                        label: t('admin.support.termsTitle'),
                        label_default: 'Terms of Service Link:',
                        help_text: t('admin.support.termsDesc'),
                        help_text_default: 'Link to the terms under which users may use your online service. By default, this includes the "Mattermost Conditions of Use (End Users)" explaining the terms under which Mattermost software is provided to end users. If you change the default link to add your own terms for using the service you provide, your new terms must include a link to the default terms so end users are aware of the Mattermost Conditions of Use (End User) for Mattermost software.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SupportSettings.PrivacyPolicyLink',
                        label: t('admin.support.privacyTitle'),
                        label_default: 'Privacy Policy Link:',
                        help_text: t('admin.support.privacyDesc'),
                        help_text_default: 'The URL for the Privacy link on the login and sign-up pages. If this field is empty, the Privacy link is hidden from users.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SupportSettings.AboutLink',
                        label: t('admin.support.aboutTitle'),
                        label_default: 'About Link:',
                        help_text: t('admin.support.aboutDesc'),
                        help_text_default: 'The URL for the About link on the Mattermost login and sign-up pages. If this field is empty, the About link is hidden from users.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SupportSettings.ReportAProblemLink',
                        label: t('admin.support.problemTitle'),
                        label_default: 'Report a Problem Link:',
                        help_text: t('admin.support.problemDesc'),
                        help_text_default: 'The URL for the Report a Problem link in the Main Menu. If this field is empty, the link is removed from the Main Menu.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'NativeAppSettings.AppDownloadLink',
                        label: t('admin.customization.appDownloadLinkTitle'),
                        label_default: 'Mattermost Apps Download Page Link:',
                        help_text: t('admin.customization.appDownloadLinkDesc'),
                        help_text_default: 'Add a link to a download page for the Mattermost apps. When a link is present, an option to "Download Mattermost Apps" will be added in the Main Menu so users can find the download page. Leave this field blank to hide the option from the Main Menu.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'NativeAppSettings.AndroidAppDownloadLink',
                        label: t('admin.customization.androidAppDownloadLinkTitle'),
                        label_default: 'Android App Download Link:',
                        help_text: t('admin.customization.androidAppDownloadLinkDesc'),
                        help_text_default: 'Add a link to download the Android app. Users who access the site on a mobile web browser will be prompted with a page giving them the option to download the app. Leave this field blank to prevent the page from appearing.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'NativeAppSettings.IosAppDownloadLink',
                        label: t('admin.customization.iosAppDownloadLinkTitle'),
                        label_default: 'iOS App Download Link:',
                        help_text: t('admin.customization.iosAppDownloadLinkDesc'),
                        help_text_default: 'Add a link to download the iOS app. Users who access the site on a mobile web browser will be prompted with a page giving them the option to download the app. Leave this field blank to prevent the page from appearing.',
                    },
                ],
            },
        },
        localization: {
            url: 'site_config/localization',
            title: t('admin.sidebar.localization'),
            title_default: 'Localization',
            schema: {
                id: 'LocalizationSettings',
                name: t('admin.site.localization'),
                name_default: 'Localization',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_LANGUAGE,
                        key: 'LocalizationSettings.DefaultServerLocale',
                        label: t('admin.general.localization.serverLocaleTitle'),
                        label_default: 'Default Server Language:',
                        help_text: t('admin.general.localization.serverLocaleDescription'),
                        help_text_default: 'Default language for system messages. Changing this will require a server restart before taking effect.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_LANGUAGE,
                        key: 'LocalizationSettings.DefaultClientLocale',
                        label: t('admin.general.localization.clientLocaleTitle'),
                        label_default: 'Default Client Language:',
                        help_text: t('admin.general.localization.clientLocaleDescription'),
                        help_text_default: 'Default language for newly created users and pages where the user hasn\'t logged in.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_LANGUAGE,
                        key: 'LocalizationSettings.AvailableLocales',
                        label: t('admin.general.localization.availableLocalesTitle'),
                        label_default: 'Available Languages:',
                        help_text: t('admin.general.localization.availableLocalesDescription'),
                        help_text_markdown: true,
                        help_text_default: 'Set which languages are available for users in Account Settings (leave this field blank to have all supported languages available). If you\'re manually adding new languages, the **Default Client Language** must be added before saving this setting.\n \nWould like to help with translations? Join the [Mattermost Translation Server](!http://translate.mattermost.com/) to contribute.',
                        multiple: true,
                        no_result: t('admin.general.localization.availableLocalesNoResults'),
                        no_result_default: 'No results found',
                        not_present: t('admin.general.localization.availableLocalesNotPresent'),
                        not_present_default: 'The default client language must be included in the available list',
                    },
                ],
            },
        },
        users_and_teams: {
            url: 'site_config/users_and_teams',
            title: t('admin.sidebar.usersAndTeams'),
            title_default: 'Users and Teams',
            schema: {
                id: 'UserAndTeamsSettings',
                name: t('admin.site.usersAndTeams'),
                name_default: 'Users and Teams',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_PERMISSION,
                        key: 'TeamSettings.EnableTeamCreation',
                        label: t('admin.team.teamCreationTitle'),
                        label_default: 'Enable Team Creation: ',
                        help_text: t('admin.team.teamCreationDescription'),
                        help_text_default: 'When false, only System Administrators can create teams.',
                        permissions_mapping_name: 'enableTeamCreation',
                        isHidden: it.licensed,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'TeamSettings.MaxUsersPerTeam',
                        label: t('admin.team.maxUsersTitle'),
                        label_default: 'Max Users Per Team:',
                        help_text: t('admin.team.maxUsersDescription'),
                        help_text_default: 'Maximum total number of users per team, including both active and inactive users.',
                        placeholder: t('admin.team.maxUsersExample'),
                        placeholder_default: 'E.g.: "25"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'TeamSettings.MaxChannelsPerTeam',
                        label: t('admin.team.maxChannelsTitle'),
                        label_default: 'Max Channels Per Team:',
                        help_text: t('admin.team.maxChannelsDescription'),
                        help_text_default: 'Maximum total number of channels per team, including both active and archived channels.',
                        placeholder: t('admin.team.maxChannelsExample'),
                        placeholder_default: 'E.g.: "100"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'TeamSettings.RestrictDirectMessage',
                        label: t('admin.team.restrictDirectMessage'),
                        label_default: 'Enable users to open Direct Message channels with:',
                        help_text: t('admin.team.restrictDirectMessageDesc'),
                        help_text_default: '"Any user on the Mattermost server" enables users to open a Direct Message channel with any user on the server, even if they are not on any teams together. "Any member of the team" limits the ability in the Direct Messages "More" menu to only open Direct Message channels with users who are in the same team.\n \nNote: This setting only affects the UI, not permissions on the server.',
                        options: [
                            {
                                value: 'any',
                                display_name: t('admin.team.restrict_direct_message_any'),
                                display_name_default: 'Any user on the Mattermost server',
                            },
                            {
                                value: 'team',
                                display_name: t('admin.team.restrict_direct_message_team'),
                                display_name_default: 'Any member of the team',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'TeamSettings.TeammateNameDisplay',
                        label: t('admin.team.teammateNameDisplay'),
                        label_default: 'Teammate Name Display:',
                        help_text: t('admin.team.teammateNameDisplayDesc'),
                        help_text_default: 'Set how to display users\' names in posts and the Direct Messages list.',
                        options: [
                            {
                                value: Constants.TEAMMATE_NAME_DISPLAY.SHOW_USERNAME,
                                display_name: t('admin.team.showUsername'),
                                display_name_default: 'Show username (default)',
                            },
                            {
                                value: Constants.TEAMMATE_NAME_DISPLAY.SHOW_NICKNAME_FULLNAME,
                                display_name: t('admin.team.showNickname'),
                                display_name_default: 'Show nickname if one exists, otherwise show first and last name',
                            },
                            {
                                value: Constants.TEAMMATE_NAME_DISPLAY.SHOW_FULLNAME,
                                display_name: t('admin.team.showFullname'),
                                display_name_default: 'Show first and last name',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.LockTeammateNameDisplay',
                        label: t('admin.lockTeammateNameDisplay'),
                        label_default: 'Lock Teammate Name Display for all users: ',
                        help_text: t('admin.lockTeammateNameDisplayHelpText'),
                        help_text_default: 'When true, disables users\' ability to change settings under Main Menu > Account Settings > Display > Teammate Name Display.',
                        isHidden: it.isnt(it.licensedForFeature('LockTeammateNameDisplay')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_PERMISSION,
                        key: 'TeamSettings.EditOthersPosts',
                        label: t('admin.team.editOthersPostsTitle'),
                        label_default: 'Allow Team Administrators to edit others posts:',
                        help_text: t('admin.team.editOthersPostsDesc'),
                        help_text_default: 'When true, Team Administrators and System Administrators can edit other user\'s posts.  When false, only System Administrators can edit other user\'s posts.',
                        permissions_mapping_name: 'editOthersPosts',
                        isHidden: it.licensed,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.ExperimentalViewArchivedChannels',
                        label: t('admin.viewArchivedChannelsTitle'),
                        label_default: 'Allow users to view archived channels: ',
                        help_text: t('admin.viewArchivedChannelsHelpText'),
                        help_text_default: '(Beta) When true, allows users to view, share and search for content of channels that have been archived. Users can only view the content in channels of which they were a member before the channel was archived.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'PrivacySettings.ShowEmailAddress',
                        label: t('admin.privacy.showEmailTitle'),
                        label_default: 'Show Email Address:',
                        help_text: t('admin.privacy.showEmailDescription'),
                        help_text_default: 'When false, hides the email address of members from everyone except System Administrators.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'PrivacySettings.ShowFullName',
                        label: t('admin.privacy.showFullNameTitle'),
                        label_default: 'Show Full Name:',
                        help_text: t('admin.privacy.showFullNameDescription'),
                        help_text_default: 'When false, hides the full name of members from everyone except System Administrators. Username is shown in place of full name.',
                    },
                ],
            },
        },
        notifications: {
            url: 'environment/notifications',
            title: t('admin.sidebar.notifications'),
            title_default: 'Notifications',
            schema: {
                id: 'notifications',
                name: t('admin.environment.notifications'),
                name_default: 'Notifications',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.EnableConfirmNotificationsToChannel',
                        label: t('admin.environment.notifications.enableConfirmNotificationsToChannel.label'),
                        label_default: 'Show @channel and @all and group mention confirmation dialog:',
                        help_text: t('admin.environment.notifications.enableConfirmNotificationsToChannel.help'),
                        help_text_default: 'When true, users will be prompted to confirm when posting @channel, @all and group mentions in channels with over five members. When false, no confirmation is required.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.SendEmailNotifications',
                        label: t('admin.environment.notifications.enable.label'),
                        label_default: 'Enable Email Notifications:',
                        help_text: t('admin.environment.notifications.enable.help'),
                        help_text_default: 'Typically set to true in production. When true, Mattermost attempts to send email notifications. When false, email invitations and user account setting change emails are still sent as long as the SMTP server is configured. Developers may set this field to false to skip email setup for faster development.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.EnablePreviewModeBanner',
                        label: t('admin.environment.notifications.enablePreviewModeBanner.label'),
                        label_default: 'Enable Preview Mode Banner:',
                        help_text: t('admin.environment.notifications.enablePreviewModeBanner.help'),
                        help_text_default: 'When true, the Preview Mode banner is displayed so users are aware that email notifications are disabled. When false, the Preview Mode banner is not displayed to users.',
                        isDisabled: it.either(
                            it.stateIsTrue('EmailSettings.SendEmailNotifications'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.EnableEmailBatching',
                        label: t('admin.environment.notifications.enableEmailBatching.label'),
                        label_default: 'Enable Email Batching:',
                        help_text: t('admin.environment.notifications.enableEmailBatching.help'),
                        help_text_default: 'When true, users will have email notifications for multiple direct messages and mentions combined into a single email. Batching will occur at a default interval of 15 minutes, configurable in Account Settings > Notifications.',
                        isDisabled: it.either(
                            it.stateIsFalse('EmailSettings.SendEmailNotifications'),
                            it.configIsTrue('ClusterSettings', 'Enable'),
                            it.configIsFalse('ServiceSettings', 'SiteURL'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'EmailSettings.EmailNotificationContentsType',
                        label: t('admin.environment.notifications.contents.label'),
                        label_default: 'Email Notification Contents:',
                        help_text: t('admin.environment.notifications.contents.help'),
                        help_text_default: '**Send full message contents** - Sender name and channel are included in email notifications. Typically used for compliance reasons if Mattermost contains confidential information and policy dictates it cannot be stored in email.\n  **Send generic description with only sender name** - Only the name of the person who sent the message, with no information about channel name or message contents are included in email notifications. Typically used for compliance reasons if Mattermost contains confidential information and policy dictates it cannot be stored in email.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensedForFeature('EmailNotificationContents')),
                        options: [
                            {
                                value: 'full',
                                display_name: t('admin.environment.notifications.contents.full'),
                                display_name_default: 'Send full message contents',
                            },
                            {
                                value: 'generic',
                                display_name: t('admin.environment.notifications.contents.generic'),
                                display_name_default: 'Send generic description with only sender name',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.FeedbackName',
                        label: t('admin.environment.notifications.notificationDisplay.label'),
                        label_default: 'Notification Display Name:',
                        placeholder: t('admin.environment.notifications.notificationDisplay.placeholder'),
                        placeholder_default: 'Ex: "Mattermost Notification", "System", "No-Reply"',
                        help_text: t('admin.environment.notifications.notificationDisplay.help'),
                        help_text_default: 'Display name on email account used when sending notification emails from Mattermost.',
                        isDisabled: it.stateIsFalse('EmailSettings.SendEmailNotifications'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.FeedbackEmail',
                        label: t('admin.environment.notifications.feedbackEmail.label'),
                        label_default: 'Notification From Address:',
                        placeholder: t('admin.environment.notifications.feedbackEmail.placeholder'),
                        placeholder_default: 'Ex: "mattermost@yourcompany.com", "admin@yourcompany.com"',
                        help_text: t('admin.environment.notifications.feedbackEmail.help'),
                        help_text_default: 'Email address displayed on email account used when sending notification emails from Mattermost.',
                        isDisabled: it.stateIsFalse('EmailSettings.SendEmailNotifications'),
                        isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.ReplyToAddress',
                        label: t('admin.environment.notifications.replyToAddress.label'),
                        label_default: 'Notification Reply-To Address:',
                        placeholder: t('admin.environment.notifications.replyToAddress.placeholder'),
                        placeholder_default: 'Ex: "mattermost@yourcompany.com", "admin@yourcompany.com"',
                        help_text: t('admin.environment.notifications.replyToAddress.help'),
                        help_text_default: 'Email address used in the Reply-To header when sending notification emails from Mattermost.',
                        isDisabled: it.stateIsFalse('EmailSettings.SendEmailNotifications'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.FeedbackOrganization',
                        label: t('admin.environment.notifications.feedbackOrganization.label'),
                        label_default: 'Notification Footer Mailing Address:',
                        placeholder: t('admin.environment.notifications.feedbackOrganization.placeholder'),
                        placeholder_default: 'Ex: "© ABC Corporation, 565 Knight Way, Palo Alto, California, 94305, USA"',
                        help_text: t('admin.environment.notifications.feedbackOrganization.help'),
                        help_text_default: 'Organization name and address displayed on email notifications from Mattermost, such as "© ABC Corporation, 565 Knight Way, Palo Alto, California, 94305, USA". If the field is left empty, the organization name and address will not be displayed.',
                        isDisabled: it.stateIsFalse('EmailSettings.SendEmailNotifications'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'EmailSettings.PushNotificationContents',
                        label: t('admin.environment.notifications.pushContents.label'),
                        label_default: 'Push Notification Contents:',
                        help_text: t('admin.environment.notifications.pushContents.help'),
                        help_text_default: '**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents.\n **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents.\n **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple\'s Push Notification Service (APNS) or Google\'s Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an "https" protocol to encrypt the connection and protect confidential information sent in messages.',
                        help_text_markdown: true,
                        isHidden: it.licensedForFeature('IDLoadedPushNotifications'),
                        options: [
                            {
                                value: 'generic_no_channel',
                                display_name: t('admin.environment.notifications.pushContents.genericNoChannel'),
                                display_name_default: 'Generic description with only sender name',
                            },
                            {
                                value: 'generic',
                                display_name: t('admin.environment.notifications.pushContents.generic'),
                                display_name_default: 'Generic description with sender and channel names',
                            },
                            {
                                value: 'full',
                                display_name: t('admin.environment.notifications.pushContents.full'),
                                display_name_default: 'Full message content sent in the notification payload',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'EmailSettings.PushNotificationContents',
                        label: t('admin.environment.notifications.pushContents.label'),
                        label_default: 'Push Notification Contents:',
                        help_text: t('admin.environment.notifications.pushContents.withIdLoaded.help'),
                        help_text_default: '**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents.\n **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents.\n **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple\'s Push Notification Service (APNS) or Google\'s Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an "https" protocol to encrypt the connection and protect confidential information sent in messages.\n **Full message content fetched from the server on receipt** - The notification payload relayed through APNS or FCM contains no message content, instead it contains a unique message ID used to fetch message content from the server when a push notification is received by a device. If the server cannot be reached, a generic notification will be displayed.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensedForFeature('IDLoadedPushNotifications')),
                        options: [
                            {
                                value: 'generic_no_channel',
                                display_name: t('admin.environment.notifications.pushContents.genericNoChannel'),
                                display_name_default: 'Generic description with only sender name',
                            },
                            {
                                value: 'generic',
                                display_name: t('admin.environment.notifications.pushContents.generic'),
                                display_name_default: 'Generic description with sender and channel names',
                            },
                            {
                                value: 'full',
                                display_name: t('admin.environment.notifications.pushContents.full'),
                                display_name_default: 'Full message content sent in the notification payload',
                            },
                            {
                                value: 'id_loaded',
                                display_name: t('admin.environment.notifications.pushContents.idLoaded'),
                                display_name_default: 'Full message content fetched from the server on receipt',
                            },
                        ],
                    },
                ],
            },
        },
        announcement_banner: {
            url: 'site_config/announcement_banner',
            title: t('admin.sidebar.announcement'),
            title_default: 'Announcement Banner',
            isHidden: it.isnt(it.licensed),
            schema: {
                id: 'AnnouncementSettings',
                name: t('admin.site.announcementBanner'),
                name_default: 'Announcement Banner',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'AnnouncementSettings.EnableBanner',
                        label: t('admin.customization.announcement.enableBannerTitle'),
                        label_default: 'Enable Announcement Banner:',
                        help_text: t('admin.customization.announcement.enableBannerDesc'),
                        help_text_default: 'Enable an announcement banner across all teams.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'AnnouncementSettings.BannerText',
                        label: t('admin.customization.announcement.bannerTextTitle'),
                        label_default: 'Banner Text:',
                        help_text: t('admin.customization.announcement.bannerTextDesc'),
                        help_text_default: 'Text that will appear in the announcement banner.',
                        isDisabled: it.stateIsFalse('AnnouncementSettings.EnableBanner'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_COLOR,
                        key: 'AnnouncementSettings.BannerColor',
                        label: t('admin.customization.announcement.bannerColorTitle'),
                        label_default: 'Banner Color:',
                        isDisabled: it.stateIsFalse('AnnouncementSettings.EnableBanner'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_COLOR,
                        key: 'AnnouncementSettings.BannerTextColor',
                        label: t('admin.customization.announcement.bannerTextColorTitle'),
                        label_default: 'Banner Text Color:',
                        isDisabled: it.stateIsFalse('AnnouncementSettings.EnableBanner'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'AnnouncementSettings.AllowBannerDismissal',
                        label: t('admin.customization.announcement.allowBannerDismissalTitle'),
                        label_default: 'Allow Banner Dismissal:',
                        help_text: t('admin.customization.announcement.allowBannerDismissalDesc'),
                        help_text_default: 'When true, users can dismiss the banner until its next update. When false, the banner is permanently visible until it is turned off by the System Admin.',
                        isDisabled: it.stateIsFalse('AnnouncementSettings.EnableBanner'),
                    },
                ],
            },
        },
        emoji: {
            url: 'site_config/emoji',
            title: t('admin.sidebar.emoji'),
            title_default: 'Emoji',
            schema: {
                id: 'EmojiSettings',
                name: t('admin.site.emoji'),
                name_default: 'Emoji',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableEmojiPicker',
                        label: t('admin.customization.enableEmojiPickerTitle'),
                        label_default: 'Enable Emoji Picker:',
                        help_text: t('admin.customization.enableEmojiPickerDesc'),
                        help_text_default: 'The emoji picker allows users to select emoji to add as reactions or use in messages. Enabling the emoji picker with a large number of custom emoji may slow down performance.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableCustomEmoji',
                        label: t('admin.customization.enableCustomEmojiTitle'),
                        label_default: 'Enable Custom Emoji:',
                        help_text: t('admin.customization.enableCustomEmojiDesc'),
                        help_text_default: 'Enable users to create custom emoji for use in messages. When enabled, Custom Emoji settings can be accessed by switching to a team and clicking the three dots above the channel sidebar, and selecting "Custom Emoji".',
                    },
                ],
            },
        },
        posts: {
            url: 'site_config/posts',
            title: t('admin.sidebar.posts'),
            title_default: 'Posts',
            schema: {
                id: 'PostSettings',
                name: t('admin.site.posts'),
                name_default: 'Posts',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableLinkPreviews',
                        label: t('admin.customization.enableLinkPreviewsTitle'),
                        label_default: 'Enable Link Previews:',
                        help_text: t('admin.customization.enableLinkPreviewsDesc'),
                        help_text_default: 'Display a preview of website content, image links and YouTube links below the message when available. The server must be connected to the internet and have access through the firewall (if applicable) to the websites from which previews are expected. Users can disable these previews from Account Settings > Display > Website Link Previews.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableSVGs',
                        label: t('admin.customization.enableSVGsTitle'),
                        label_default: 'Enable SVGs:',
                        help_text: t('admin.customization.enableSVGsDesc'),
                        help_text_default: 'Enable previews for SVG file attachments and allow them to appear in messages.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableLatex',
                        label: t('admin.customization.enableLatexTitle'),
                        label_default: 'Enable Latex Rendering:',
                        help_text: t('admin.customization.enableLatexDesc'),
                        help_text_default: 'Enable rendering of Latex code. If false, Latex code will be highlighted only.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_CUSTOM,
                        component: CustomUrlSchemesSetting,
                        key: 'DisplaySettings.CustomUrlSchemes',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.GoogleDeveloperKey',
                        label: t('admin.service.googleTitle'),
                        label_default: 'Google API Key:',
                        placeholder: t('admin.service.googleExample'),
                        placeholder_default: 'E.g.: "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"',
                        help_text: t('admin.service.googleDescription'),
                        help_text_default: 'Set this key to enable the display of titles for embedded YouTube video previews. Without the key, YouTube previews will still be created based on hyperlinks appearing in messages or comments but they will not show the video title. View a [Google Developers Tutorial](!https://www.youtube.com/watch?v=Im69kzhpR3I) for instructions on how to obtain a key and add YouTube Data API v3 as a service to your key.',
                        help_text_markdown: true,
                        isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
                    },
                ],
            },
        },
        file_sharing_downloads: {
            url: 'site_config/file_sharing_downloads',
            title: t('admin.sidebar.fileSharingDownloads'),
            title_default: 'File Sharing and Downloads',
            schema: {
                id: 'FileSharingDownloads',
                name: t('admin.site.fileSharingDownloads'),
                name_default: 'File Sharing and Downloads',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.EnableFileAttachments',
                        label: t('admin.file.enableFileAttachments'),
                        label_default: 'Allow File Sharing:',
                        help_text: t('admin.file.enableFileAttachmentsDesc'),
                        help_text_default: 'When false, disables file sharing on the server. All file and image uploads on messages are forbidden across clients and devices, including mobile.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.EnableMobileUpload',
                        label: t('admin.file.enableMobileUploadTitle'),
                        label_default: 'Allow File Uploads on Mobile:',
                        help_text: t('admin.file.enableMobileUploadDesc'),
                        help_text_default: 'When false, disables file uploads on mobile apps. If Allow File Sharing is set to true, users can still upload files from a mobile web browser.',
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.EnableMobileDownload',
                        label: t('admin.file.enableMobileDownloadTitle'),
                        label_default: 'Allow File Downloads on Mobile:',
                        help_text: t('admin.file.enableMobileDownloadDesc'),
                        help_text_default: 'When false, disables file downloads on mobile apps. Users can still download files from a mobile web browser.',
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                    },
                ],
            },
        },
        public_links: {
            url: 'site_config/public_links',
            title: t('admin.sidebar.publicLinks'),
            title_default: 'Public Links',
            schema: {
                id: 'PublicLinkSettings',
                name: t('admin.site.public_links'),
                name_default: 'Public Links',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'FileSettings.EnablePublicLink',
                        label: t('admin.image.shareTitle'),
                        label_default: 'Enable Public File Links: ',
                        help_text: t('admin.image.shareDescription'),
                        help_text_default: 'Allow users to share public links to files and images.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_GENERATED,
                        key: 'FileSettings.PublicLinkSalt',
                        label: t('admin.image.publicLinkTitle'),
                        label_default: 'Public Link Salt:',
                        help_text: t('admin.image.publicLinkDescription'),
                        help_text_default: '32-character salt added to signing of public image links. Randomly generated on install. Click "Regenerate" to create new salt.',
                    },
                ],
            },
        },
    },
    authentication: {
        icon: 'fa-shield',
        sectionTitle: t('admin.sidebar.authentication'),
        sectionTitleDefault: 'Authentication',
        signup: {
            url: 'authentication/signup',
            title: t('admin.sidebar.signup'),
            title_default: 'Signup',
            schema: {
                id: 'SignupSettings',
                name: t('admin.authentication.signup'),
                name_default: 'Signup',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.EnableUserCreation',
                        label: t('admin.team.userCreationTitle'),
                        label_default: 'Enable Account Creation: ',
                        help_text: t('admin.team.userCreationDescription'),
                        help_text_default: 'When false, the ability to create accounts is disabled. The create account button displays error when pressed.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'TeamSettings.RestrictCreationToDomains',
                        label: t('admin.team.restrictTitle'),
                        label_default: 'Restrict new system and team members to specified email domains:',
                        help_text: t('admin.team.restrictDescription'),
                        help_text_default: 'New user accounts are restricted to the above specified email domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org"). New teams can only be created by users from the above domain(s). This setting only affects email login for users.',
                        placeholder: t('admin.team.restrictExample'),
                        placeholder_default: 'E.g.: "corp.mattermost.com, mattermost.org"',
                        isHidden: it.licensed,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'TeamSettings.RestrictCreationToDomains',
                        label: t('admin.team.restrictTitle'),
                        label_default: 'Restrict new system and team members to specified email domains:',
                        help_text: t('admin.team.restrictGuestDescription'),
                        help_text_default: 'New user accounts are restricted to the above specified email domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org"). New teams can only be created by users from the above domain(s). This setting affects email login for users. For Guest users, please add domains under Signup > Guest Access.',
                        placeholder: t('admin.team.restrictExample'),
                        placeholder_default: 'E.g.: "corp.mattermost.com, mattermost.org"',
                        isHidden: it.isnt(it.licensed),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.EnableOpenServer',
                        label: t('admin.team.openServerTitle'),
                        label_default: 'Enable Open Server: ',
                        help_text: t('admin.team.openServerDescription'),
                        help_text_default: 'When true, anyone can signup for a user account on this server without the need to be invited.',
                        isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableEmailInvitations',
                        label: t('admin.team.emailInvitationsTitle'),
                        label_default: 'Enable Email Invitations: ',
                        help_text: t('admin.team.emailInvitationsDescription'),
                        help_text_default: 'When true users can invite others to the system using email.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        key: 'InvalidateEmailInvitesButton',
                        action: invalidateAllEmailInvites,
                        label: t('admin.team.invalidateEmailInvitesTitle'),
                        label_default: 'Invalidate pending email invites',
                        help_text: t('admin.team.invalidateEmailInvitesDescription'),
                        help_text_default: 'This will invalidate active email invitations that have not been accepted by the user.  By default email invitations expire after 48 hours.',
                        error_message: t('admin.team.invalidateEmailInvitesFail'),
                        error_message_default: 'Unable to invalidate pending email invites: {error}',
                        success_message: t('admin.team.invalidateEmailInvitesSuccess'),
                        success_message_default: 'Pending email invitations invalidated successfully',
                    },
                ],
            },
        },
        email: {
            url: 'authentication/email',
            title: t('admin.sidebar.email'),
            title_default: 'Email',
            schema: {
                id: 'EmailSettings',
                name: t('admin.authentication.email'),
                name_default: 'Email',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.EnableSignUpWithEmail',
                        label: t('admin.email.allowSignupTitle'),
                        label_default: 'Enable account creation with email:',
                        help_text: t('admin.email.allowSignupDescription'),
                        help_text_default: 'When true, Mattermost allows account creation using email and password. This value should be false only when you want to limit sign up to a single sign-on service like AD/LDAP, SAML or GitLab.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.RequireEmailVerification',
                        label: t('admin.email.requireVerificationTitle'),
                        label_default: 'Require Email Verification: ',
                        help_text: t('admin.email.requireVerificationDescription'),
                        help_text_default: 'Typically set to true in production. When true, Mattermost requires email verification after account creation prior to allowing login. Developers may set this field to false to skip sending verification emails for faster development.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.EnableSignInWithEmail',
                        label: t('admin.email.allowEmailSignInTitle'),
                        label_default: 'Enable sign-in with email:',
                        help_text: t('admin.email.allowEmailSignInDescription'),
                        help_text_default: 'When true, Mattermost allows users to sign in using their email and password.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.EnableSignInWithUsername',
                        label: t('admin.email.allowUsernameSignInTitle'),
                        label_default: 'Enable sign-in with username:',
                        help_text: t('admin.email.allowUsernameSignInDescription'),
                        help_text_default: 'When true, users with email login can sign in using their username and password. This setting does not affect AD/LDAP login.',
                    },
                ],
            },
        },
        password: {
            url: 'authentication/password',
            title: t('admin.sidebar.password'),
            title_default: 'Password',
            searchableStrings: [
                'user.settings.security.passwordMinLength',
                'admin.security.password',
                ['admin.password.minimumLength', {max: '', min: ''}],
                ['admin.password.minimumLengthDescription', {max: '', min: ''}],
                'passwordRequirements',
                'admin.password.lowercase',
                'admin.password.uppercase',
                'admin.password.number',
                'admin.password.symbol',
                'admin.password.preview',
                'admin.service.attemptTitle',
                'admin.service.attemptDescription',
            ],
            schema: {
                id: 'PasswordSettings',
                component: PasswordSettings,
            },
        },
        mfa: {
            url: 'authentication/mfa',
            title: t('admin.sidebar.mfa'),
            title_default: 'MFA',
            schema: {
                id: 'ServiceSettings',
                name: t('admin.authentication.mfa'),
                name_default: 'Multi-factor Authentication',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BANNER,
                        label: t('admin.mfa.bannerDesc'),
                        label_default: '[Multi-factor authentication](!https://docs.mattermost.com/deployment/auth.html) is available for accounts with AD/LDAP or email login. If other login methods are used, MFA should be configured with the authentication provider.',
                        label_markdown: true,
                        banner_type: 'info',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableMultifactorAuthentication',
                        label: t('admin.service.mfaTitle'),
                        label_default: 'Enable Multi-factor Authentication:',
                        help_text: t('admin.service.mfaDesc'),
                        help_text_default: 'When true, users with AD/LDAP or email login can add multi-factor authentication to their account using Google Authenticator.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnforceMultifactorAuthentication',
                        label: t('admin.service.enforceMfaTitle'),
                        label_default: 'Enforce Multi-factor Authentication:',
                        help_text: t('admin.service.enforceMfaDesc'),
                        help_text_markdown: true,
                        help_text_default: 'When true, [multi-factor authentication](!https://docs.mattermost.com/deployment/auth.html) is required for login. New users will be required to configure MFA on signup. Logged in users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.',
                        isDisabled: it.stateIsFalse('ServiceSettings.EnableMultifactorAuthentication'),
                        isHidden: it.isnt(it.licensedForFeature('MFA')),
                    },
                ],
            },
        },
        ldap: {
            url: 'authentication/ldap',
            title: t('admin.sidebar.ldap'),
            title_default: 'AD/LDAP',
            isHidden: it.isnt(it.licensedForFeature('LDAP')),
            schema: {
                id: 'LdapSettings',
                name: t('admin.authentication.ldap'),
                name_default: 'AD/LDAP',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LdapSettings.Enable',
                        label: t('admin.ldap.enableTitle'),
                        label_default: 'Enable sign-in with AD/LDAP:',
                        help_text: t('admin.ldap.enableDesc'),
                        help_text_default: 'When true, Mattermost allows login using AD/LDAP',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LdapSettings.EnableSync',
                        label: t('admin.ldap.enableSyncTitle'),
                        label_default: 'Enable Synchronization with AD/LDAP:',
                        help_text: t('admin.ldap.enableSyncDesc'),
                        help_text_default: 'When true, Mattermost periodically synchronizes users from AD/LDAP. When false, user attributes are updated from AD/LDAP during user login only.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LdapServer',
                        label: t('admin.ldap.serverTitle'),
                        label_default: 'AD/LDAP Server:',
                        help_text: t('admin.ldap.serverDesc'),
                        help_text_default: 'The domain or IP address of AD/LDAP server.',
                        placeholder: t('admin.ldap.serverEx'),
                        placeholder_default: 'E.g.: "10.0.0.23"',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'LdapSettings.LdapPort',
                        label: t('admin.ldap.portTitle'),
                        label_default: 'AD/LDAP Port:',
                        help_text: t('admin.ldap.portDesc'),
                        help_text_default: 'The port Mattermost will use to connect to the AD/LDAP server. Default is 389.',
                        placeholder: t('admin.ldap.portEx'),
                        placeholder_default: 'E.g.: "389"',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'LdapSettings.ConnectionSecurity',
                        label: t('admin.connectionSecurityTitle'),
                        label_default: 'Connection Security:',
                        help_text: DefinitionConstants.CONNECTION_SECURITY_HELP_TEXT_LDAP,
                        options: [
                            {
                                value: '',
                                display_name: t('admin.connectionSecurityNone'),
                                display_name_default: 'None',
                            },
                            {
                                value: 'TLS',
                                display_name: t('admin.connectionSecurityTls'),
                                display_name_default: 'TLS (Recommended)',
                            },
                            {
                                value: 'STARTTLS',
                                display_name: t('admin.connectionSecurityStart'),
                                display_name_default: 'STARTTLS',
                            },
                        ],
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LdapSettings.SkipCertificateVerification',
                        label: t('admin.ldap.skipCertificateVerification'),
                        label_default: 'Skip Certificate Verification:',
                        help_text: t('admin.ldap.skipCertificateVerificationDesc'),
                        help_text_default: 'Skips the certificate verification step for TLS or STARTTLS connections. Skipping certificate verification is not recommended for production environments where TLS is required.',
                        isDisabled: it.stateIsFalse('LdapSettings.ConnectionSecurity'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.BaseDN',
                        label: t('admin.ldap.baseTitle'),
                        label_default: 'BaseDN:',
                        help_text: t('admin.ldap.baseDesc'),
                        help_text_default: 'The Base DN is the Distinguished Name of the location where Mattermost should start its search for user and group objects in the AD/LDAP tree.',
                        placeholder: t('admin.ldap.baseEx'),
                        placeholder_default: 'E.g.: "ou=Unit Name,dc=corp,dc=example,dc=com"',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.BindUsername',
                        label: t('admin.ldap.bindUserTitle'),
                        label_default: 'Bind Username:',
                        help_text: t('admin.ldap.bindUserDesc'),
                        help_text_default: 'The username used to perform the AD/LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the AD/LDAP tree specified in the BaseDN field.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.BindPassword',
                        label: t('admin.ldap.bindPwdTitle'),
                        label_default: 'Bind Password:',
                        help_text: t('admin.ldap.bindPwdDesc'),
                        help_text_default: 'Password of the user given in "Bind Username".',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.UserFilter',
                        label: t('admin.ldap.userFilterTitle'),
                        label_default: 'User Filter:',
                        help_text: t('admin.ldap.userFilterDisc'),
                        help_text_default: '(Optional) Enter an AD/LDAP filter to use when searching for user objects. Only the users selected by the query will be able to access Mattermost. For Active Directory, the query to filter out disabled users is (&(objectCategory=Person)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))).',
                        placeholder: t('admin.ldap.userFilterEx'),
                        placeholder_default: 'Ex. "(objectClass=user)"',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.GuestFilter',
                        label: t('admin.ldap.guestFilterTitle'),
                        label_default: 'Guest Filter:',
                        help_text: t('admin.ldap.guestFilterFilterDesc'),
                        help_text_default: '(Optional) Requires Guest Access to be enabled before being applied. Enter an AD/LDAP filter to use when searching for guest objects. Only the users selected by the query will be able to access Mattermost as Guests. Guests are prevented from accessing teams or channels upon logging in until they are assigned a team and at least one channel.\n \nNote: If this filter is removed/changed, active guests will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console > User Management**.\n \n \nExisting members that are identified by this attribute as a guest will be demoted from a member to a guest when they are asked to login next. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to guests in **System Console > User Management ** to ensure access is restricted immediately.',
                        help_text_markdown: true,
                        placeholder: t('admin.ldap.guestFilterEx'),
                        placeholder_default: 'E.g.: "(objectClass=user)"',
                        isDisabled: it.either(
                            it.configIsFalse('GuestAccountsSettings', 'Enable'),
                            it.both(
                                it.stateIsFalse('LdapSettings.Enable'),
                                it.stateIsFalse('LdapSettings.EnableSync'),
                            ),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'LdapSettings.EnableAdminFilter',
                        label: t('admin.ldap.enableAdminFilterTitle'),
                        label_default: 'Enable Admin Filter:',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.AdminFilter',
                        label: t('admin.ldap.adminFilterTitle'),
                        label_default: 'Admin Filter:',
                        help_text: t('admin.ldap.adminFilterFilterDesc'),
                        help_text_default: '(Optional) Enter an AD/LDAP filter to use for designating System Admins. The users selected by the query will have access to your Mattermost server as System Admins. By default, System Admins have complete access to the Mattermost System Console.\n \nExisting members that are identified by this attribute will be promoted from member to System Admin upon next login. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to members in **System Console > User Management** to ensure access is restricted immediately.\n \nNote: If this filter is removed/changed, System Admins that were promoted via this filter will be demoted to members and will not retain access to the System Console. When this filter is not in use, System Admins can be manually promoted/demoted in **System Console > User Management**.',
                        help_text_markdown: true,
                        placeholder: t('admin.ldap.adminFilterEx'),
                        placeholder_default: 'E.g.: "(objectClass=user)"',
                        isDisabled: it.either(
                            it.stateIsFalse('LdapSettings.EnableAdminFilter'),
                            it.both(
                                it.stateIsFalse('LdapSettings.Enable'),
                                it.stateIsFalse('LdapSettings.EnableSync'),
                            ),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.GroupFilter',
                        label: t('admin.ldap.groupFilterTitle'),
                        label_default: 'Group Filter:',
                        help_text: t('admin.ldap.groupFilterFilterDesc'),
                        help_text_markdown: true,
                        help_text_default: '(Optional) Enter an AD/LDAP filter to use when searching for group objects. Only the groups selected by the query will be available to Mattermost. From [User Management > Groups]({siteURL}/admin_console/user_management/groups), select which AD/LDAP groups should be linked and configured.',
                        help_text_values: {siteURL: getSiteURL()},
                        placeholder: t('admin.ldap.groupFilterEx'),
                        placeholder_default: 'E.g.: "(objectClass=group)"',
                        isDisabled: it.stateIsFalse('LdapSettings.EnableSync'),
                        isHidden: it.isnt(it.licensedForFeature('LDAPGroups')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.GroupDisplayNameAttribute',
                        label: t('admin.ldap.groupDisplayNameAttributeTitle'),
                        label_default: 'Group Display Name Attribute:',
                        help_text: t('admin.ldap.groupDisplayNameAttributeDesc'),
                        help_text_default: 'The attribute in the AD/LDAP server used to populate the group display names.',
                        placeholder: t('admin.ldap.groupDisplayNameAttributeEx'),
                        placeholder_default: 'E.g.: "cn"',
                        isDisabled: it.stateIsFalse('LdapSettings.EnableSync'),
                        isHidden: it.isnt(it.licensedForFeature('LDAPGroups')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.GroupIdAttribute',
                        label: t('admin.ldap.groupIdAttributeTitle'),
                        label_default: 'Group ID Attribute:',
                        help_text: t('admin.ldap.groupIdAttributeDesc'),
                        help_text_default: 'The attribute in the AD/LDAP server used as a unique identifier for Groups. This should be a AD/LDAP attribute with a value that does not change such as `entryUUID` for LDAP or `objectGUID` for Active Directory.',
                        help_text_markdown: true,
                        placeholder: t('admin.ldap.groupIdAttributeEx'),
                        placeholder_default: 'E.g.: "objectGUID" or "entryUUID"',
                        isDisabled: it.stateIsFalse('LdapSettings.EnableSync'),
                        isHidden: it.isnt(it.licensedForFeature('LDAPGroups')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.FirstNameAttribute',
                        label: t('admin.ldap.firstnameAttrTitle'),
                        label_default: 'First Name Attribute:',
                        placeholder: t('admin.ldap.firstnameAttrEx'),
                        placeholder_default: 'E.g.: "givenName"',
                        help_text: t('admin.ldap.firstnameAttrDesc'),
                        help_text_default: '(Optional) The attribute in the AD/LDAP server used to populate the first name of users in Mattermost. When set, users cannot edit their first name, since it is synchronized with the LDAP server. When left blank, users can set their first name in Account Settings.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LastNameAttribute',
                        label: t('admin.ldap.lastnameAttrTitle'),
                        label_default: 'Last Name Attribute:',
                        placeholder: t('admin.ldap.lastnameAttrEx'),
                        placeholder_default: 'E.g.: "sn"',
                        help_text: t('admin.ldap.lastnameAttrDesc'),
                        help_text_default: '(Optional) The attribute in the AD/LDAP server used to populate the last name of users in Mattermost. When set, users cannot edit their last name, since it is synchronized with the LDAP server. When left blank, users can set their last name in Account Settings.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.NicknameAttribute',
                        label: t('admin.ldap.nicknameAttrTitle'),
                        label_default: 'Nickname Attribute:',
                        placeholder: t('admin.ldap.nicknameAttrEx'),
                        placeholder_default: 'E.g.: "nickname"',
                        help_text: t('admin.ldap.nicknameAttrDesc'),
                        help_text_default: '(Optional) The attribute in the AD/LDAP server used to populate the nickname of users in Mattermost. When set, users cannot edit their nickname, since it is synchronized with the LDAP server. When left blank, users can set their nickname in Account Settings.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.PositionAttribute',
                        label: t('admin.ldap.positionAttrTitle'),
                        label_default: 'Position Attribute:',
                        placeholder: t('admin.ldap.positionAttrEx'),
                        placeholder_default: 'E.g.: "title"',
                        help_text: t('admin.ldap.positionAttrDesc'),
                        help_text_default: '(Optional) The attribute in the AD/LDAP server used to populate the position field in Mattermost. When set, users cannot edit their position, since it is synchronized with the LDAP server. When left blank, users can set their position in Account Settings.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.EmailAttribute',
                        label: t('admin.ldap.emailAttrTitle'),
                        label_default: 'Email Attribute:',
                        placeholder: t('admin.ldap.emailAttrEx'),
                        placeholder_default: 'E.g.: "mail" or "userPrincipalName"',
                        help_text: t('admin.ldap.emailAttrDesc'),
                        help_text_default: 'The attribute in the AD/LDAP server used to populate the email address field in Mattermost.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.PictureAttribute',
                        label: t('admin.ldap.pictureAttrTitle'),
                        label_default: 'Profile Picture Attribute:',
                        placeholder: t('admin.ldap.pictureAttrEx'),
                        placeholder_default: 'E.g.: "thumbnailPhoto" or "jpegPhoto"',
                        help_text: t('admin.ldap.pictureAttrDesc'),
                        help_text_default: 'The attribute in the AD/LDAP server used to populate the profile picture in Mattermost.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.UsernameAttribute',
                        label: t('admin.ldap.usernameAttrTitle'),
                        label_default: 'Username Attribute:',
                        placeholder: t('admin.ldap.usernameAttrEx'),
                        placeholder_default: 'E.g.: "sAMAccountName"',
                        help_text: t('admin.ldap.usernameAttrDesc'),
                        help_text_default: 'The attribute in the AD/LDAP server used to populate the username field in Mattermost. This may be the same as the Login ID Attribute.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.IdAttribute',
                        label: t('admin.ldap.idAttrTitle'),
                        label_default: 'ID Attribute: ',
                        placeholder: t('admin.ldap.idAttrEx'),
                        placeholder_default: 'E.g.: "objectGUID" or "uid"',
                        help_text: t('admin.ldap.idAttrDesc'),
                        help_text_markdown: true,
                        help_text_default: 'The attribute in the AD/LDAP server used as a unique identifier in Mattermost. It should be an AD/LDAP attribute with a value that does not change such as `uid` for LDAP or `objectGUID` for Active Directory. If a user\'s ID Attribute changes, it will create a new Mattermost account unassociated with their old one.\n \nIf you need to change this field after users have already logged in, use the [mattermost ldap idmigrate](!https://about.mattermost.com/default-mattermost-ldap-idmigrate) CLI tool.',
                        isDisabled: it.both(
                            it.stateEquals('LdapSettings.Enable', false),
                            it.stateEquals('LdapSettings.EnableSync', false),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LoginIdAttribute',
                        label: t('admin.ldap.loginAttrTitle'),
                        label_default: 'Login ID Attribute: ',
                        placeholder: t('admin.ldap.loginIdAttrEx'),
                        placeholder_default: 'E.g.: "sAMAccountName"',
                        help_text: t('admin.ldap.loginAttrDesc'),
                        help_text_markdown: true,
                        help_text_default: 'The attribute in the AD/LDAP server used to log in to Mattermost. Normally this attribute is the same as the "Username Attribute" field above.\n \nIf your team typically uses domain/username to log in to other services with AD/LDAP, you may enter domain/username in this field to maintain consistency between sites.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LoginFieldName',
                        label: t('admin.ldap.loginNameTitle'),
                        label_default: 'Sign-in Field Default Text:',
                        placeholder: t('admin.ldap.loginNameEx'),
                        placeholder_default: 'E.g.: "AD/LDAP Username"',
                        help_text: t('admin.ldap.loginNameDesc'),
                        help_text_default: 'The placeholder text that appears in the login field on the login page. Defaults to "AD/LDAP Username".',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'LdapSettings.SyncIntervalMinutes',
                        label: t('admin.ldap.syncIntervalTitle'),
                        label_default: 'Synchronization Interval (minutes):',
                        help_text: t('admin.ldap.syncIntervalHelpText'),
                        help_text_default: 'AD/LDAP Synchronization updates Mattermost user information to reflect updates on the AD/LDAP server. For example, when a user\'s name changes on the AD/LDAP server, the change updates in Mattermost when synchronization is performed. Accounts removed from or disabled in the AD/LDAP server have their Mattermost accounts set to "Inactive" and have their account sessions revoked. Mattermost performs synchronization on the interval entered. For example, if 60 is entered, Mattermost synchronizes every 60 minutes.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'LdapSettings.MaxPageSize',
                        label: t('admin.ldap.maxPageSizeTitle'),
                        label_default: 'Maximum Page Size:',
                        placeholder: t('admin.ldap.maxPageSizeEx'),
                        placeholder_default: 'E.g.: "2000"',
                        help_text: t('admin.ldap.maxPageSizeHelpText'),
                        help_text_default: 'The maximum number of users the Mattermost server will request from the AD/LDAP server at one time. 0 is unlimited.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'LdapSettings.QueryTimeout',
                        label: t('admin.ldap.queryTitle'),
                        label_default: 'Query Timeout (seconds):',
                        placeholder: t('admin.ldap.queryEx'),
                        placeholder_default: 'E.g.: "60"',
                        help_text: t('admin.ldap.queryDesc'),
                        help_text_default: 'The timeout value for queries to the AD/LDAP server. Increase if you are getting timeout errors caused by a slow AD/LDAP server.',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        action: ldapTest,
                        key: 'LdapSettings.LdapTest',
                        label: t('admin.ldap.ldap_test_button'),
                        label_default: 'AD/LDAP Test',
                        help_text: t('admin.ldap.testHelpText'),
                        help_text_markdown: true,
                        help_text_default: 'Tests if the Mattermost server can connect to the AD/LDAP server specified. Please review "System Console > Logs" and [documentation](!https://mattermost.com/default-ldap-docs) to troubleshoot errors.',
                        error_message: t('admin.ldap.testFailure'),
                        error_message_default: 'AD/LDAP Test Failure: {error}',
                        success_message: t('admin.ldap.testSuccess'),
                        success_message_default: 'AD/LDAP Test Successful',
                        isDisabled: it.both(
                            it.stateIsFalse('LdapSettings.Enable'),
                            it.stateIsFalse('LdapSettings.EnableSync'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_JOBSTABLE,
                        job_type: Constants.JobTypes.LDAP_SYNC,
                        label: t('admin.ldap.sync_button'),
                        label_default: 'AD/LDAP Synchronize Now',
                        help_text: t('admin.ldap.syncNowHelpText'),
                        help_text_markdown: true,
                        help_text_default: 'Initiates an AD/LDAP synchronization immediately. See the table below for status of each synchronization. Please review "System Console > Logs" and [documentation](!https://mattermost.com/default-ldap-docs) to troubleshoot errors.',
                        isDisabled: it.stateIsFalse('LdapSettings.EnableSync'),
                        render_job: (job) => {
                            let ldapUsers = 0;
                            let deleteCount = 0;
                            let updateCount = 0;
                            let linkedLdapGroupsCount; // Deprecated.
                            let totalLdapGroupsCount = 0;
                            let groupDeleteCount = 0;
                            let groupMemberDeleteCount = 0;
                            let groupMemberAddCount = 0;

                            if (job && job.data) {
                                if (job.data.ldap_users_count && job.data.ldap_users_count.length > 0) {
                                    ldapUsers = job.data.ldap_users_count;
                                }

                                if (job.data.delete_count && job.data.delete_count.length > 0) {
                                    deleteCount = job.data.delete_count;
                                }

                                if (job.data.update_count && job.data.update_count.length > 0) {
                                    updateCount = job.data.update_count;
                                }

                                // Deprecated groups count representing the number of linked LDAP groups.
                                if (job.data.ldap_groups_count) {
                                    linkedLdapGroupsCount = job.data.ldap_groups_count;
                                }

                                // Groups count representing the total number of LDAP groups available based on
                                // the configured based DN and groups filter.
                                if (job.data.total_ldap_groups_count) {
                                    totalLdapGroupsCount = job.data.total_ldap_groups_count;
                                }

                                if (job.data.group_delete_count) {
                                    groupDeleteCount = job.data.group_delete_count;
                                }

                                if (job.data.group_member_delete_count) {
                                    groupMemberDeleteCount = job.data.group_member_delete_count;
                                }

                                if (job.data.group_member_add_count) {
                                    groupMemberAddCount = job.data.group_member_add_count;
                                }
                            }

                            return (
                                <span>
                                    <FormattedMessage
                                        id={linkedLdapGroupsCount ? 'admin.ldap.jobExtraInfo' : 'admin.ldap.jobExtraInfoTotal'}
                                        defaultMessage={linkedLdapGroupsCount ? 'Scanned {ldapUsers, number} LDAP users and {ldapGroups, number} linked groups.' : 'Scanned {ldapUsers, number} LDAP users and {ldapGroups, number} groups.'}
                                        values={{
                                            ldapUsers,
                                            ldapGroups: linkedLdapGroupsCount || totalLdapGroupsCount, // Show the old count for jobs records containing the old JSON key.
                                        }}
                                    />
                                    <ul>
                                        {updateCount > 0 &&
                                            <li>
                                                <FormattedMessage
                                                    id='admin.ldap.jobExtraInfo.updatedUsers'
                                                    defaultMessage='Updated {updateCount, number} users.'
                                                    values={{
                                                        updateCount,
                                                    }}
                                                />
                                            </li>
                                        }
                                        {deleteCount > 0 &&
                                            <li>
                                                <FormattedMessage
                                                    id='admin.ldap.jobExtraInfo.deactivatedUsers'
                                                    defaultMessage='Deactivated {deleteCount, number} users.'
                                                    values={{
                                                        deleteCount,
                                                    }}
                                                />
                                            </li>
                                        }
                                        {groupDeleteCount > 0 &&
                                            <li>
                                                <FormattedMessage
                                                    id='admin.ldap.jobExtraInfo.deletedGroups'
                                                    defaultMessage='Deleted {groupDeleteCount, number} groups.'
                                                    values={{
                                                        groupDeleteCount,
                                                    }}
                                                />
                                            </li>
                                        }
                                        {groupMemberDeleteCount > 0 &&
                                            <li>
                                                <FormattedMessage
                                                    id='admin.ldap.jobExtraInfo.deletedGroupMembers'
                                                    defaultMessage='Deleted {groupMemberDeleteCount, number} group members.'
                                                    values={{
                                                        groupMemberDeleteCount,
                                                    }}
                                                />
                                            </li>
                                        }
                                        {groupMemberAddCount > 0 &&
                                            <li>
                                                <FormattedMessage
                                                    id='admin.ldap.jobExtraInfo.addedGroupMembers'
                                                    defaultMessage='Added {groupMemberAddCount, number} group members.'
                                                    values={{
                                                        groupMemberAddCount,
                                                    }}
                                                />
                                            </li>
                                        }
                                    </ul>
                                </span>
                            );
                        },
                    },
                ],
            },
        },
        ldap_feature_discovery: {
            url: 'authentication/ldap',
            isDiscovery: true,
            title: t('admin.sidebar.ldap'),
            title_default: 'AD/LDAP',
            isHidden: it.either(
                it.licensedForFeature('LDAP'),
                it.isnt(it.enterpriseReady),
            ),
            schema: {
                id: 'LdapSettings',
                name: t('admin.authentication.ldap'),
                name_default: 'AD/LDAP',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_CUSTOM,
                        component: LDAPFeatureDiscovery,
                        key: 'LDAPFeatureDiscovery',
                    },
                ],
            },
        },
        saml: {
            url: 'authentication/saml',
            title: t('admin.sidebar.saml'),
            title_default: 'SAML 2.0',
            isHidden: it.isnt(it.licensedForFeature('SAML')),
            schema: {
                id: 'SamlSettings',
                name: t('admin.authentication.saml'),
                name_default: 'SAML 2.0',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.Enable',
                        label: t('admin.saml.enableTitle'),
                        label_default: 'Enable Login With SAML 2.0:',
                        help_text: t('admin.saml.enableDescription'),
                        help_text_default: 'When true, Mattermost allows login using SAML 2.0. Please see [documentation](!http://docs.mattermost.com/deployment/sso-saml.html) to learn more about configuring SAML for Mattermost.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.EnableSyncWithLdap',
                        label: t('admin.saml.enableSyncWithLdapTitle'),
                        label_default: 'Enable Synchronizing SAML Accounts With AD/LDAP:',
                        help_text: t('admin.saml.enableSyncWithLdapDescription'),
                        help_text_default: 'When true, Mattermost periodically synchronizes SAML user attributes, including user deactivation and removal, from AD/LDAP. Enable and configure synchronization settings at **Authentication > AD/LDAP**. When false, user attributes are updated from SAML during user login. See [documentation](!https://about.mattermost.com/default-saml-ldap-sync) to learn more.',
                        help_text_markdown: true,
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.EnableSyncWithLdapIncludeAuth',
                        label: t('admin.saml.enableSyncWithLdapIncludeAuthTitle'),
                        label_default: 'Override SAML bind data with AD/LDAP information:',
                        help_text: t('admin.saml.enableSyncWithLdapIncludeAuthDescription'),
                        help_text_default: 'When true, Mattermost will override the SAML ID attribute with the AD/LDAP ID attribute if configured or override the SAML Email attribute with the AD/LDAP Email attribute if SAML ID attribute is not present.  This will allow you automatically migrate users from Email binding to ID binding to prevent creation of new users when an email address changes for a user. Moving from true to false, will remove the override from happening.\n \n**Note:** SAML IDs must match the LDAP IDs to prevent disabling of user accounts.  Please review [documentation](!https://docs.mattermost.com/deployment/sso-saml-ldapsync.html) for more information.',
                        help_text_markdown: true,
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Enable'),
                            it.stateIsFalse('SamlSettings.EnableSyncWithLdap'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.IdpMetadataUrl',
                        label: t('admin.saml.idpMetadataUrlTitle'),
                        label_default: 'Identity Provider Metadata URL:',
                        help_text: t('admin.saml.idpMetadataUrlDesc'),
                        help_text_default: 'The Metadata URL for the Identity Provider you use for SAML requests',
                        placeholder: t('admin.saml.idpMetadataUrlEx'),
                        placeholder_default: 'E.g.: "https://idp.example.org/SAML2/saml/metadata"',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BUTTON,
                        key: 'getSamlMetadataFromIDPButton',
                        action: getSamlMetadataFromIdp,
                        label: t('admin.saml.getSamlMetadataFromIDPUrl'),
                        label_default: 'Get SAML Metadata from IdP',
                        loading: t('admin.saml.getSamlMetadataFromIDPFetching'),
                        loading_default: 'Fetching...',
                        error_message: t('admin.saml.getSamlMetadataFromIDPFail'),
                        error_message_default: 'SAML Metadata URL did not connect and pull data successfully',
                        success_message: t('admin.saml.getSamlMetadataFromIDPSuccess'),
                        success_message_default: 'SAML Metadata retrieved successfully. Two fields below have been updated',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Enable'),
                            it.stateEquals('SamlSettings.IdpMetadataUrl', ''),
                        ),
                        sourceUrlKey: 'SamlSettings.IdpMetadataUrl',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.IdpUrl',
                        label: t('admin.saml.idpUrlTitle'),
                        label_default: 'SAML SSO URL:',
                        help_text: t('admin.saml.idpUrlDesc'),
                        help_text_default: 'The URL where Mattermost sends a SAML request to start login sequence.',
                        placeholder: t('admin.saml.idpUrlEx'),
                        placeholder_default: 'E.g.: "https://idp.example.org/SAML2/SSO/Login"',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                        setFromMetadataField: 'idp_url',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.IdpDescriptorUrl',
                        label: t('admin.saml.idpDescriptorUrlTitle'),
                        label_default: 'Identity Provider Issuer URL:',
                        help_text: t('admin.saml.idpDescriptorUrlDesc'),
                        help_text_default: 'The issuer URL for the Identity Provider you use for SAML requests.',
                        placeholder: t('admin.saml.idpDescriptorUrlEx'),
                        placeholder_default: 'E.g.: "https://idp.example.org/SAML2/issuer"',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                        setFromMetadataField: 'idp_descriptor_url',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_FILE_UPLOAD,
                        key: 'SamlSettings.IdpCertificateFile',
                        label: t('admin.saml.idpCertificateFileTitle'),
                        label_default: 'Identity Provider Public Certificate:',
                        help_text: t('admin.saml.idpCertificateFileDesc'),
                        help_text_default: 'The public authentication certificate issued by your Identity Provider.',
                        remove_help_text: t('admin.saml.idpCertificateFileRemoveDesc'),
                        remove_help_text_default: 'Remove the public authentication certificate issued by your Identity Provider.',
                        remove_button_text: t('admin.saml.remove.idp_certificate'),
                        remove_button_text_default: 'Remove Identity Provider Certificate',
                        removing_text: t('admin.saml.removing.certificate'),
                        removing_text_default: 'Removing Certificate...',
                        uploading_text: t('admin.saml.uploading.certificate'),
                        uploading_text_default: 'Uploading Certificate...',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                        fileType: '.crt,.cer,.cert,.pem',
                        upload_action: uploadIdpSamlCertificate,
                        set_action: setSamlIdpCertificateFromMetadata,
                        remove_action: removeIdpSamlCertificate,
                        setFromMetadataField: 'idp_public_certificate',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.Verify',
                        label: t('admin.saml.verifyTitle'),
                        label_default: 'Verify Signature:',
                        help_text: t('admin.saml.verifyDescription'),
                        help_text_default: 'When false, Mattermost will not verify that the signature sent from a SAML Response matches the Service Provider Login URL. Disabling verification is not recommended for production environments.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.AssertionConsumerServiceURL',
                        label: t('admin.saml.assertionConsumerServiceURLTitle'),
                        label_default: 'Service Provider Login URL:',
                        help_text: t('admin.saml.assertionConsumerServiceURLPopulatedDesc'),
                        help_text_default: 'This field is also known as the Assertion Consumer Service URL.',
                        placeholder: t('admin.saml.assertionConsumerServiceURLEx'),
                        placeholder_default: 'E.g.: "https://<your-mattermost-url>/login/sso/saml"',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Enable'),
                            it.stateIsFalse('SamlSettings.Verify'),
                        ),
                        onConfigLoad: (value, config) => {
                            const siteUrl = config.ServiceSettings.SiteURL;
                            if (siteUrl.length > 0 && value.length === 0) {
                                const addSlashIfNeeded = siteUrl[siteUrl.length - 1] === '/' ? '' : '/';
                                return `${siteUrl}${addSlashIfNeeded}login/sso/saml`;
                            }
                            return value;
                        },
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.ServiceProviderIdentifier',
                        label: t('admin.saml.serviceProviderIdentifierTitle'),
                        label_default: 'Service Provider Identifier:',
                        help_text: t('admin.saml.serviceProviderIdentifierDesc'),
                        help_text_default: 'The unique identifier for the Service Provider, usually the same as Service Provider Login URL. In ADFS, this MUST match the Relying Party Identifier.',
                        placeholder: t('admin.saml.serviceProviderIdentifierEx'),
                        placeholder_default: 'E.g.: "https://<your-mattermost-url>/login/sso/saml"',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.Encrypt',
                        label: t('admin.saml.encryptTitle'),
                        label_default: 'Enable Encryption:',
                        help_text: t('admin.saml.encryptDescription'),
                        help_text_default: 'When false, Mattermost will not decrypt SAML Assertions encrypted with your Service Provider Public Certificate. Disabling encryption is not recommended for production environments.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_FILE_UPLOAD,
                        key: 'SamlSettings.PrivateKeyFile',
                        label: t('admin.saml.privateKeyFileTitle'),
                        label_default: 'Service Provider Private Key:',
                        help_text: t('admin.saml.privateKeyFileFileDesc'),
                        help_text_default: 'The private key used to decrypt SAML Assertions from the Identity Provider.',
                        remove_help_text: t('admin.saml.privateKeyFileFileRemoveDesc'),
                        remove_help_text_default: 'Remove the private key used to decrypt SAML Assertions from the Identity Provider.',
                        remove_button_text: t('admin.saml.remove.privKey'),
                        remove_button_text_default: 'Remove Service Provider Private Key',
                        removing_text: t('admin.saml.removing.privKey'),
                        removing_text_default: 'Removing Private Key...',
                        uploading_text: t('admin.saml.uploading.privateKey'),
                        uploading_text_default: 'Uploading Private Key...',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Enable'),
                            it.stateIsFalse('SamlSettings.Encrypt'),
                        ),
                        fileType: '.key',
                        upload_action: uploadPrivateSamlCertificate,
                        remove_action: removePrivateSamlCertificate,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_FILE_UPLOAD,
                        key: 'SamlSettings.PublicCertificateFile',
                        label: t('admin.saml.publicCertificateFileTitle'),
                        label_default: 'Service Provider Public Certificate:',
                        help_text: t('admin.saml.publicCertificateFileDesc'),
                        help_text_default: 'The certificate used to generate the signature on a SAML request to the Identity Provider for a service provider initiated SAML login, when Mattermost is the Service Provider.',
                        remove_help_text: t('admin.saml.publicCertificateFileRemoveDesc'),
                        remove_help_text_default: 'Remove the certificate used to generate the signature on a SAML request to the Identity Provider for a service provider initiated SAML login, when Mattermost is the Service Provider.',
                        remove_button_text: t('admin.saml.remove.sp_certificate'),
                        remove_button_text_default: 'Remove Service Provider Certificate',
                        removing_text: t('admin.saml.removing.certificate'),
                        removing_text_default: 'Removing Certificate...',
                        uploading_text: t('admin.saml.uploading.certificate'),
                        uploading_text_default: 'Uploading Certificate...',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Enable'),
                            it.stateIsFalse('SamlSettings.Encrypt'),
                        ),
                        fileType: '.crt,.cer',
                        upload_action: uploadPublicSamlCertificate,
                        remove_action: removePublicSamlCertificate,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.SignRequest',
                        label: t('admin.saml.signRequestTitle'),
                        label_default: 'Sign Request:',
                        help_text: t('admin.saml.signRequestDescription'),
                        help_text_default: 'When true, Mattermost will sign the SAML request using your private key. When false, Mattermost will not sign the SAML request.',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Encrypt'),
                            it.stateIsFalse('SamlSettings.PrivateKeyFile'),
                            it.stateIsFalse('SamlSettings.PublicCertificateFile'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'SamlSettings.SignatureAlgorithm',
                        label: t('admin.saml.signatureAlgorithmTitle'),
                        label_default: 'Signature Algorithm',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Encrypt'),
                            it.stateIsFalse('SamlSettings.SignRequest'),
                        ),
                        options: [
                            {
                                value: SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA1,
                                display_name: t('admin.saml.signatureAlgorithmDisplay.sha1'),
                                display_name_default: SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA1,
                                help_text: t('admin.saml.signatureAlgorithmDescription.sha1'),
                                help_text_default: 'Specify the Signature algorithm used to sign the request (RSAwithSHA1). Please see more information provided at http://www.w3.org/2000/09/xmldsig#rsa-sha1',
                            },
                            {
                                value: SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA256,
                                display_name: t('admin.saml.signatureAlgorithmDisplay.sha256'),
                                display_name_default: SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA256,
                                help_text: t('admin.saml.signatureAlgorithmDescription.sha256'),
                                help_text_default: 'Specify the Signature algorithm used to sign the request (RSAwithSHA256). Please see more information provided at http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 [section 6.4.2 RSA (PKCS#1 v1.5)]',
                            },
                            {
                                value: SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA512,
                                display_name: t('admin.saml.signatureAlgorithmDisplay.sha512'),
                                display_name_default: SAML_SETTINGS_SIGNATURE_ALGORITHM_SHA512,
                                help_text: t('admin.saml.signatureAlgorithmDescription.sha512'),
                                help_text_default: 'Specify the Signature algorithm used to sign the request (RSAwithSHA512). Please see more information provided at http://www.w3.org/2001/04/xmldsig-more#rsa-sha512',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'SamlSettings.CanonicalAlgorithm',
                        label: t('admin.saml.canonicalAlgorithmTitle'),
                        label_default: 'Canonicalization Algorithm',
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.Encrypt'),
                            it.stateIsFalse('SamlSettings.SignRequest'),
                        ),
                        options: [
                            {
                                value: SAML_SETTINGS_CANONICAL_ALGORITHM_C14N,
                                display_name: t('admin.saml.canonicalAlgorithmDisplay.n10'),
                                display_name_default: 'Exclusive XML Canonicalization 1.0 (omit comments)',
                                help_text: t('admin.saml.canonicalAlgorithmDescription.exc'),
                                help_text_default: 'Specify the Canonicalization algorithm (Exclusive XML Canonicalization 1.0).  Please see more information provided at http://www.w3.org/2001/10/xml-exc-c14n#',
                            },
                            {
                                value: SAML_SETTINGS_CANONICAL_ALGORITHM_C14N11,
                                display_name: t('admin.saml.canonicalAlgorithmDisplay.n11'),
                                display_name_default: 'Canonical XML 1.1 (omit comments)',
                                help_text: t('admin.saml.canonicalAlgorithmDescription.c14'),
                                help_text_default: 'Specify the Canonicalization algorithm (Canonical XML 1.1).  Please see more information provided at http://www.w3.org/2006/12/xml-c14n11',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.EmailAttribute',
                        label: t('admin.saml.emailAttrTitle'),
                        label_default: 'Email Attribute:',
                        placeholder: t('admin.saml.emailAttrEx'),
                        placeholder_default: 'E.g.: "Email" or "PrimaryEmail"',
                        help_text: t('admin.saml.emailAttrDesc'),
                        help_text_default: 'The attribute in the SAML Assertion that will be used to populate the email addresses of users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.UsernameAttribute',
                        label: t('admin.saml.usernameAttrTitle'),
                        label_default: 'Username Attribute:',
                        placeholder: t('admin.saml.usernameAttrEx'),
                        placeholder_default: 'E.g.: "Username"',
                        help_text: t('admin.saml.usernameAttrDesc'),
                        help_text_default: 'The attribute in the SAML Assertion that will be used to populate the username field in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.IdAttribute',
                        label: t('admin.saml.idAttrTitle'),
                        label_default: 'Id Attribute:',
                        placeholder: t('admin.saml.idAttrEx'),
                        placeholder_default: 'E.g.: "Id"',
                        help_text: t('admin.saml.idAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion that will be used to bind users from SAML to users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.GuestAttribute',
                        label: t('admin.saml.guestAttrTitle'),
                        label_default: 'Guest Attribute:',
                        placeholder: t('admin.saml.guestAttrEx'),
                        placeholder_default: 'E.g.: "usertype=Guest" or "isGuest=true"',
                        help_text: t('admin.saml.guestAttrDesc'),
                        help_text_default: '(Optional) Requires Guest Access to be enabled before being applied. The attribute in the SAML Assertion that will be used to apply a guest role to users in Mattermost. Guests are prevented from accessing teams or channels upon logging in until they are assigned a team and at least one channel.\n \nNote: If this attribute is removed/changed from your guest user in SAML and the user is still active, they will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console > User Management**.\n \n \nExisting members that are identified by this attribute as a guest will be demoted from a member to a guest when they are asked to login next. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to guests in **System Console > User Management ** to ensure access is restricted immediately.',
                        help_text_markdown: true,
                        isDisabled: it.either(
                            it.configIsFalse('GuestAccountsSettings', 'Enable'),
                            it.stateIsFalse('SamlSettings.Enable'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'SamlSettings.EnableAdminAttribute',
                        label: t('admin.saml.enableAdminAttrTitle'),
                        label_default: 'Enable Admin Attribute:',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.AdminAttribute',
                        label: t('admin.saml.adminAttrTitle'),
                        label_default: 'Admin Attribute:',
                        placeholder: t('admin.saml.adminAttrEx'),
                        placeholder_default: 'E.g.: "usertype=Admin" or "isAdmin=true"',
                        help_text: t('admin.saml.adminAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion for designating System Admins. The users selected by the query will have access to your Mattermost server as System Admins. By default, System Admins have complete access to the Mattermost System Console.\n \nExisting members that are identified by this attribute will be promoted from member to System Admin upon next login. The next login is based upon Session lengths set in **System Console > Session Lengths.** It is highly recommend to manually demote users to members in **System Console > User Management** to ensure access is restricted immediately.\n \nNote: If this filter is removed/changed, System Admins that were promoted via this filter will be demoted to members and will not retain access to the System Console. When this filter is not in use, System Admins can be manually promoted/demoted in **System Console > User Management**.',
                        help_text_markdown: true,
                        isDisabled: it.either(
                            it.stateIsFalse('SamlSettings.EnableAdminAttribute'),
                            it.stateIsFalse('SamlSettings.Enable'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.FirstNameAttribute',
                        label: t('admin.saml.firstnameAttrTitle'),
                        label_default: 'First Name Attribute:',
                        placeholder: t('admin.saml.firstnameAttrEx'),
                        placeholder_default: 'E.g.: "FirstName"',
                        help_text: t('admin.saml.firstnameAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion that will be used to populate the first name of users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.LastNameAttribute',
                        label: t('admin.saml.lastnameAttrTitle'),
                        label_default: 'Last Name Attribute:',
                        placeholder: t('admin.saml.lastnameAttrEx'),
                        placeholder_default: 'E.g.: "LastName"',
                        help_text: t('admin.saml.lastnameAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion that will be used to populate the last name of users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.NicknameAttribute',
                        label: t('admin.saml.nicknameAttrTitle'),
                        label_default: 'Nickname Attribute:',
                        placeholder: t('admin.saml.nicknameAttrEx'),
                        placeholder_default: 'E.g.: "Nickname"',
                        help_text: t('admin.saml.nicknameAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion that will be used to populate the nickname of users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.PositionAttribute',
                        label: t('admin.saml.positionAttrTitle'),
                        label_default: 'Position Attribute:',
                        placeholder: t('admin.saml.positionAttrEx'),
                        placeholder_default: 'E.g.: "Role"',
                        help_text: t('admin.saml.positionAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion that will be used to populate the position of users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.LocaleAttribute',
                        label: t('admin.saml.localeAttrTitle'),
                        label_default: 'Preferred Language Attribute:',
                        placeholder: t('admin.saml.localeAttrEx'),
                        placeholder_default: 'E.g.: "Locale" or "PrimaryLanguage"',
                        help_text: t('admin.saml.localeAttrDesc'),
                        help_text_default: '(Optional) The attribute in the SAML Assertion that will be used to populate the language of users in Mattermost.',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.LoginButtonText',
                        label: t('admin.saml.loginButtonTextTitle'),
                        label_default: 'Login Button Text:',
                        placeholder: t('admin.saml.loginButtonTextEx'),
                        placeholder_default: 'E.g.: "OKTA"',
                        help_text: t('admin.saml.loginButtonTextDesc'),
                        help_text_default: '(Optional) The text that appears in the login button on the login page. Defaults to "SAML".',
                        isDisabled: it.stateIsFalse('SamlSettings.Enable'),
                    },
                ],
            },
        },
        saml_feature_discovery: {
            url: 'authentication/saml',
            isDiscovery: true,
            title: t('admin.sidebar.saml'),
            title_default: 'SAML 2.0',
            isHidden: it.either(
                it.licensedForFeature('SAML'),
                it.isnt(it.enterpriseReady),
            ),
            schema: {
                id: 'SamlSettings',
                name: t('admin.authentication.saml'),
                name_default: 'SAML 2.0',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_CUSTOM,
                        component: SAMLFeatureDiscovery,
                        key: 'SAMLFeatureDiscovery',
                    },
                ],
            },
        },
        gitlab: {
            url: 'authentication/gitlab',
            title: t('admin.sidebar.gitlab'),
            title_default: 'GitLab',
            isHidden: it.licensed,
            schema: {
                id: 'GitLabSettings',
                name: t('admin.authentication.gitlab'),
                name_default: 'GitLab',
                onConfigLoad: (config) => {
                    const newState = {};
                    newState['GitLabSettings.Url'] = config.GitLabSettings.UserApiEndpoint.replace('/api/v4/user', '');
                    return newState;
                },
                onConfigSave: (config) => {
                    const newConfig = {...config};
                    newConfig.GitLabSettings.UserApiEndpoint = config.GitLabSettings.Url.replace(/\/$/, '') + '/api/v4/user';
                    return newConfig;
                },
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'GitLabSettings.Enable',
                        label: t('admin.gitlab.enableTitle'),
                        label_default: 'Enable authentication with GitLab: ',
                        help_text: t('admin.gitlab.enableDescription'),
                        help_text_default: 'When true, Mattermost allows team creation and account signup using GitLab OAuth.\n \n1. Log in to your GitLab account and go to Profile Settings -> Applications.\n2. Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete".\n3. Then use "Application Secret Key" and "Application ID" fields from GitLab to complete the options below.\n4. Complete the Endpoint URLs below.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.Id',
                        label: t('admin.gitlab.clientIdTitle'),
                        label_default: 'Application ID:',
                        help_text: t('admin.gitlab.clientIdDescription'),
                        help_text_default: 'Obtain this value via the instructions above for logging into GitLab.',
                        placeholder: t('admin.gitlab.clientIdExample'),
                        placeholder_default: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"',
                        isDisabled: it.stateIsFalse('GitLabSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.Secret',
                        label: t('admin.gitlab.clientSecretTitle'),
                        label_default: 'Application Secret Key:',
                        help_text: t('admin.gitlab.clientSecretDescription'),
                        help_text_default: 'Obtain this value via the instructions above for logging into GitLab.',
                        placeholder: t('admin.gitlab.clientSecretExample'),
                        placeholder_default: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"',
                        isDisabled: it.stateIsFalse('GitLabSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.Url',
                        label: t('admin.gitlab.siteUrl'),
                        label_default: 'GitLab Site URL:',
                        help_text: t('admin.gitlab.siteUrlDescription'),
                        help_text_default: 'Enter the URL of your GitLab instance, e.g. https://example.com:3000. If your GitLab instance is not set up with SSL, start the URL with http:// instead of https://.',
                        placeholder: t('admin.gitlab.siteUrlExample'),
                        placeholder_default: 'E.g.: https://',
                        isDisabled: it.stateIsFalse('GitLabSettings.Enable'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.UserApiEndpoint',
                        label: t('admin.gitlab.userTitle'),
                        label_default: 'User API Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['GitLabSettings.Url']) {
                                return state['GitLabSettings.Url'].replace(/\/$/, '') + '/api/v4/user';
                            }
                            return '';
                        },
                        isDisabled: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.AuthEndpoint',
                        label: t('admin.gitlab.authTitle'),
                        label_default: 'Auth Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['GitLabSettings.Url']) {
                                return state['GitLabSettings.Url'].replace(/\/$/, '') + '/oauth/authorize';
                            }
                            return '';
                        },
                        isDisabled: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.TokenEndpoint',
                        label: t('admin.gitlab.tokenTitle'),
                        label_default: 'Token Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['GitLabSettings.Url']) {
                                return state['GitLabSettings.Url'].replace(/\/$/, '') + '/oauth/token';
                            }
                            return '';
                        },
                        isDisabled: true,
                    },
                ],
            },
        },
        oauth: {
            url: 'authentication/oauth',
            title: t('admin.sidebar.oauth'),
            title_default: 'OAuth 2.0',
            isHidden: it.isnt(it.licensed),
            schema: {
                id: 'OAuthSettings',
                name: t('admin.authentication.oauth'),
                name_default: 'OAuth 2.0',
                onConfigLoad: (config) => {
                    const newState = {};
                    if (config.GitLabSettings && config.GitLabSettings.Enable) {
                        newState.oauthType = Constants.GITLAB_SERVICE;
                    }
                    if (config.Office365Settings && config.Office365Settings.Enable) {
                        newState.oauthType = Constants.OFFICE365_SERVICE;
                    }
                    if (config.GoogleSettings && config.GoogleSettings.Enable) {
                        newState.oauthType = Constants.GOOGLE_SERVICE;
                    }

                    newState['GitLabSettings.Url'] = config.GitLabSettings.UserApiEndpoint.replace('/api/v4/user', '');

                    return newState;
                },
                onConfigSave: (config) => {
                    const newConfig = {...config};
                    newConfig.GitLabSettings = config.GitLabSettings || {};
                    newConfig.Office365Settings = config.Office365Settings || {};
                    newConfig.GoogleSettings = config.GoogleSettings || {};

                    newConfig.GitLabSettings.Enable = false;
                    newConfig.Office365Settings.Enable = false;
                    newConfig.GoogleSettings.Enable = false;
                    newConfig.GitLabSettings.UserApiEndpoint = config.GitLabSettings.Url.replace(/\/$/, '') + '/api/v4/user';

                    if (config.oauthType === Constants.GITLAB_SERVICE) {
                        newConfig.GitLabSettings.Enable = true;
                    }
                    if (config.oauthType === Constants.OFFICE365_SERVICE) {
                        newConfig.Office365Settings.Enable = true;
                    }
                    if (config.oauthType === Constants.GOOGLE_SERVICE) {
                        newConfig.GoogleSettings.Enable = true;
                    }
                    delete newConfig.oauthType;
                    return newConfig;
                },
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'oauthType',
                        label: t('admin.oauth.select'),
                        label_default: 'Select OAuth 2.0 Service Provider:',
                        options: [
                            {
                                value: 'off',
                                display_name: t('admin.oauth.off'),
                                display_name_default: 'Do not allow sign-in via an OAuth 2.0 provider.',
                            },
                            {
                                value: Constants.GITLAB_SERVICE,
                                display_name: t('admin.oauth.gitlab'),
                                display_name_default: 'GitLab',
                                help_text: t('admin.gitlab.EnableMarkdownDesc'),
                                help_text_default: '1. Log in to your GitLab account and go to Profile Settings -> Applications.\n2. Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete".\n3. Then use "Application Secret Key" and "Application ID" fields from GitLab to complete the options below.\n4. Complete the Endpoint URLs below.',
                                help_text_markdown: true,
                            },
                            {
                                value: Constants.GOOGLE_SERVICE,
                                display_name: t('admin.oauth.google'),
                                display_name_default: 'Google Apps',
                                isHidden: it.isnt(it.licensedForFeature('GoogleOAuth')),
                                help_text: t('admin.google.EnableMarkdownDesc'),
                                help_text_default: '1. [Log in](!https://accounts.google.com/login) to your Google account.\n2. Go to [https://console.developers.google.com](!https://console.developers.google.com), click **Credentials** in the left hand sidebar and enter "Mattermost - your-company-name" as the **Project Name**, then click **Create**.\n3. Click the **OAuth consent screen** header and enter "Mattermost" as the **Product name shown to users**, then click **Save**.\n4. Under the **Credentials** header, click **Create credentials**, choose **OAuth client ID** and select **Web Application**.\n5. Under **Restrictions** and **Authorized redirect URIs** enter **your-mattermost-url/signup/google/complete** (example: http://localhost:8065/signup/google/complete). Click **Create**.\n6. Paste the **Client ID** and **Client Secret** to the fields below, then click **Save**.\n7. Go to the [Google People API](!https://console.developers.google.com/apis/library/people.googleapis.com) and click *Enable*.',
                                help_text_markdown: true,
                            },
                            {
                                value: Constants.OFFICE365_SERVICE,
                                display_name: t('admin.oauth.office365'),
                                display_name_default: 'Office 365',
                                isHidden: it.isnt(it.licensedForFeature('Office365OAuth')),
                                help_text: t('admin.office365.EnableMarkdownDesc'),
                                help_text_default: '1. [Log in](!https://login.microsoftonline.com/) to your Microsoft or Office 365 account. Make sure it`s the account on the same [tenant](!https://msdn.microsoft.com/en-us/library/azure/jj573650.aspx#Anchor_0) that you would like users to log in with.\n2. Go to [https://apps.dev.microsoft.com](!https://apps.dev.microsoft.com), click **Go to app list** > **Add an app** and use "Mattermost - your-company-name" as the **Application Name**.\n3. Under **Application Secrets**, click **Generate New Password** and paste it to the **Application Secret Password** field below.\n4. Under **Platforms**, click **Add Platform**, choose **Web** and enter **your-mattermost-url/signup/office365/complete** (example: http://localhost:8065/signup/office365/complete) under **Redirect URIs**. Also uncheck **Allow Implicit Flow**.\n5. Finally, click **Save** and then paste the **Application ID** below.',
                                help_text_markdown: true,
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.Id',
                        label: t('admin.gitlab.clientIdTitle'),
                        label_default: 'Application ID:',
                        help_text: t('admin.gitlab.clientIdDescription'),
                        help_text_default: 'Obtain this value via the instructions above for logging into GitLab.',
                        placeholder: t('admin.gitlab.clientIdExample'),
                        placeholder_default: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'gitlab')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.Secret',
                        label: t('admin.gitlab.clientSecretTitle'),
                        label_default: 'Application Secret Key:',
                        help_text: t('admin.gitlab.clientSecretDescription'),
                        help_text_default: 'Obtain this value via the instructions above for logging into GitLab.',
                        placeholder: t('admin.gitlab.clientSecretExample'),
                        placeholder_default: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'gitlab')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.Url',
                        label: t('admin.gitlab.siteUrl'),
                        label_default: 'GitLab Site URL:',
                        help_text: t('admin.gitlab.siteUrlDescription'),
                        help_text_default: 'Enter the URL of your GitLab instance, e.g. https://example.com:3000. If your GitLab instance is not set up with SSL, start the URL with http:// instead of https://.',
                        placeholder: t('admin.gitlab.siteUrlExample'),
                        placeholder_default: 'E.g.: https://',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'gitlab')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.UserApiEndpoint',
                        label: t('admin.gitlab.userTitle'),
                        label_default: 'User API Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['GitLabSettings.Url']) {
                                return state['GitLabSettings.Url'].replace(/\/$/, '') + '/api/v4/user';
                            }
                            return '';
                        },
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'gitlab')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.AuthEndpoint',
                        label: t('admin.gitlab.authTitle'),
                        label_default: 'Auth Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['GitLabSettings.Url']) {
                                return state['GitLabSettings.Url'].replace(/\/$/, '') + '/oauth/authorize';
                            }
                            return '';
                        },
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'gitlab')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GitLabSettings.TokenEndpoint',
                        label: t('admin.gitlab.tokenTitle'),
                        label_default: 'Token Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['GitLabSettings.Url']) {
                                return state['GitLabSettings.Url'].replace(/\/$/, '') + '/oauth/token';
                            }
                            return '';
                        },
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'gitlab')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GoogleSettings.Id',
                        label: t('admin.google.clientIdTitle'),
                        label_default: 'Client ID:',
                        help_text: t('admin.google.clientIdDescription'),
                        help_text_default: 'The Client ID you received when registering your application with Google.',
                        placeholder: t('admin.google.clientIdExample'),
                        placeholder_default: 'E.g.: "7602141235235-url0fhs1mayfasbmop5qlfns8dh4.apps.googleusercontent.com"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'google')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GoogleSettings.Secret',
                        label: t('admin.google.clientSecretTitle'),
                        label_default: 'Client Secret:',
                        help_text: t('admin.google.clientSecretDescription'),
                        help_text_default: 'The Client Secret you received when registering your application with Google.',
                        placeholder: t('admin.google.clientSecretExample'),
                        placeholder_default: 'E.g.: "H8sz0Az-dDs2p15-7QzD231"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'google')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GoogleSettings.UserApiEndpoint',
                        label: t('admin.google.userTitle'),
                        label_default: 'User API Endpoint:',
                        dynamic_value: () => 'https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata',
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'google')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GoogleSettings.AuthEndpoint',
                        label: t('admin.google.authTitle'),
                        label_default: 'Auth Endpoint:',
                        dynamic_value: () => 'https://accounts.google.com/o/oauth2/v2/auth',
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'google')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GoogleSettings.TokenEndpoint',
                        label: t('admin.google.tokenTitle'),
                        label_default: 'Token Endpoint:',
                        dynamic_value: () => 'https://www.googleapis.com/oauth2/v4/token',
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'google')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'Office365Settings.Id',
                        label: t('admin.office365.clientIdTitle'),
                        label_default: 'Application ID:',
                        help_text: t('admin.office365.clientIdDescription'),
                        help_text_default: 'The Application/Client ID you received when registering your application with Microsoft.',
                        placeholder: t('admin.office365.clientIdExample'),
                        placeholder_default: 'E.g.: "adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'office365')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'Office365Settings.Secret',
                        label: t('admin.office365.clientSecretTitle'),
                        label_default: 'Application Secret Password:',
                        help_text: t('admin.office365.clientSecretDescription'),
                        help_text_default: 'The Application Secret Password you generated when registering your application with Microsoft.',
                        placeholder: t('admin.office365.clientSecretExample'),
                        placeholder_default: 'E.g.: "shAieM47sNBfgl20f8ci294"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'office365')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'Office365Settings.DirectoryId',
                        label: t('admin.office365.directoryIdTitle'),
                        label_default: 'Directory (tenant) ID:',
                        help_text: t('admin.office365.directoryIdDescription'),
                        help_text_default: 'The Directory (tenant) ID you received when registering your application with Microsoft.',
                        placeholder: t('admin.office365.directoryIdExample'),
                        placeholder_default: 'E.g.: "adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq"',
                        isHidden: it.isnt(it.stateEquals('oauthType', 'office365')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'Office365Settings.UserApiEndpoint',
                        label: t('admin.office365.userTitle'),
                        label_default: 'User API Endpoint:',
                        dynamic_value: () => 'https://graph.microsoft.com/v1.0/me',
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'office365')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'Office365Settings.AuthEndpoint',
                        label: t('admin.office365.authTitle'),
                        label_default: 'Auth Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['Office365Settings.DirectoryId']) {
                                return 'https://login.microsoftonline.com/' + state['Office365Settings.DirectoryId'] + '/oauth2/v2.0/authorize';
                            }
                            return 'https://login.microsoftonline.com/{directoryId}/oauth2/v2.0/authorize';
                        },
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'office365')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'Office365Settings.TokenEndpoint',
                        label: t('admin.office365.tokenTitle'),
                        label_default: 'Token Endpoint:',
                        dynamic_value: (value, config, state) => {
                            if (state['Office365Settings.DirectoryId']) {
                                return 'https://login.microsoftonline.com/' + state['Office365Settings.DirectoryId'] + '/oauth2/v2.0/token';
                            }
                            return 'https://login.microsoftonline.com/{directoryId}/oauth2/v2.0/token';
                        },
                        isDisabled: true,
                        isHidden: it.isnt(it.stateEquals('oauthType', 'office365')),
                    },
                ],
            },
        },
        guest_access: {
            url: 'authentication/guest_access',
            title: t('admin.sidebar.guest_access'),
            title_default: 'Guest Access (Beta)',
            isHidden: it.isnt(it.licensed),
            schema: {
                id: 'GuestAccountsSettings',
                name: t('admin.authentication.guest_access'),
                name_default: 'Guest Access (Beta)',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_CUSTOM,
                        component: CustomEnableDisableGuestAccountsSetting,
                        key: 'GuestAccountsSettings.Enable',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'GuestAccountsSettings.RestrictCreationToDomains',
                        label: t('admin.guest_access.whitelistedDomainsTitle'),
                        label_default: 'Whitelisted Guest Domains:',
                        help_text: t('admin.guest_access.whitelistedDomainsDescription'),
                        help_text_default: '(Optional) Guest accounts can be created at the system level from this list of allowed guest domains.',
                        help_text_markdown: true,
                        placeholder: t('admin.guest_access.whitelistedDomainsExample'),
                        placeholder_default: 'E.g.: "company.com, othercorp.org"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'GuestAccountsSettings.EnforceMultifactorAuthentication',
                        label: t('admin.guest_access.mfaTitle'),
                        label_default: 'Enforce Multi-factor Authentication: ',
                        help_text: t('admin.guest_access.mfaDescriptionMFANotEnabled'),
                        help_text_default: '[Multi-factor authentication](./mfa) is currently not enabled.',
                        help_text_markdown: true,
                        isDisabled: () => true,
                        isHidden: it.configIsTrue('ServiceSettings', 'EnableMultifactorAuthentication'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'GuestAccountsSettings.EnforceMultifactorAuthentication',
                        label: t('admin.guest_access.mfaTitle'),
                        label_default: 'Enforce Multi-factor Authentication: ',
                        help_text: t('admin.guest_access.mfaDescriptionMFANotEnforced'),
                        help_text_default: '[Multi-factor authentication](./mfa) is currently not enforced.',
                        help_text_markdown: true,
                        isDisabled: () => true,
                        isHidden: it.either(
                            it.configIsFalse('ServiceSettings', 'EnableMultifactorAuthentication'),
                            it.configIsTrue('ServiceSettings', 'EnforceMultifactorAuthentication'),
                        ),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'GuestAccountsSettings.EnforceMultifactorAuthentication',
                        label: t('admin.guest_access.mfaTitle'),
                        label_default: 'Enforce Multi-factor Authentication: ',
                        help_text: t('admin.guest_access.mfaDescription'),
                        help_text_default: 'When true, [multi-factor authentication](!https://docs.mattermost.com/deployment/auth.html) for guests is required for login. New guest users will be required to configure MFA on signup. Logged in guest users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has guest users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.',
                        help_text_markdown: true,
                        isHidden: it.either(
                            it.configIsFalse('ServiceSettings', 'EnableMultifactorAuthentication'),
                            it.configIsFalse('ServiceSettings', 'EnforceMultifactorAuthentication'),
                        ),
                    },
                ],
            },
        },
    },
    plugins: {
        icon: 'fa-plug',
        sectionTitle: t('admin.sidebar.plugins'),
        sectionTitleDefault: 'Plugins (Beta)',
        id: 'plugins',
        plugin_management: {
            url: 'plugins/plugin_management',
            title: t('admin.plugins.pluginManagement'),
            title_default: 'Plugin Management',
            searchableStrings: [
                'admin.plugin.management.title',
                'admin.plugins.settings.enable',
                'admin.plugins.settings.enableDesc',
                'admin.plugin.uploadTitle',
                'admin.plugin.installedTitle',
                'admin.plugin.installedDesc',
                'admin.plugin.uploadDesc',
                'admin.plugin.uploadDisabledDesc',
                'admin.plugins.settings.enableMarketplace',
                'admin.plugins.settings.enableMarketplaceDesc',
                'admin.plugins.settings.enableRemoteMarketplace',
                'admin.plugins.settings.enableRemoteMarketplaceDesc',
                'admin.plugins.settings.automaticPrepackagedPlugins',
                'admin.plugins.settings.automaticPrepackagedPluginsDesc',
                'admin.plugins.settings.marketplaceUrl',
                'admin.plugins.settings.marketplaceUrlDesc',
            ],
            schema: {
                id: 'PluginManagementSettings',
                component: PluginManagement,
            },
        },
        custom: {
            url: 'plugins/plugin_:plugin_id',
            schema: {
                id: 'CustomPluginSettings',
                component: CustomPluginSettings,
            },
        },
    },
    integrations: {
        icon: 'fa-sitemap',
        sectionTitle: t('admin.sidebar.integrations'),
        sectionTitleDefault: 'Integrations',
        id: 'integrations',
        integration_management: {
            url: 'integrations/integration_management',
            title: t('admin.integrations.integrationManagement'),
            title_default: 'Integration Management',
            schema: {
                id: 'CustomIntegrationSettings',
                name: t('admin.integrations.integrationManagement.title'),
                name_default: 'Integration Management',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableIncomingWebhooks',
                        label: t('admin.service.webhooksTitle'),
                        label_default: 'Enable Incoming Webhooks: ',
                        help_text: t('admin.service.webhooksDescription'),
                        help_text_default: 'When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag. See [documentation](!http://docs.mattermost.com/developer/webhooks-incoming.html) to learn more.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableOutgoingWebhooks',
                        label: t('admin.service.outWebhooksTitle'),
                        label_default: 'Enable Outgoing Webhooks: ',
                        help_text: t('admin.service.outWebhooksDesc'),
                        help_text_default: 'When true, outgoing webhooks will be allowed. See [documentation](!http://docs.mattermost.com/developer/webhooks-outgoing.html) to learn more.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableCommands',
                        label: t('admin.service.cmdsTitle'),
                        label_default: 'Enable Custom Slash Commands: ',
                        help_text: t('admin.service.cmdsDesc'),
                        help_text_default: 'When true, custom slash commands will be allowed. See [documentation](!http://docs.mattermost.com/developer/slash-commands.html) to learn more.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableOAuthServiceProvider',
                        label: t('admin.oauth.providerTitle'),
                        label_default: 'Enable OAuth 2.0 Service Provider: ',
                        help_text: t('admin.oauth.providerDescription'),
                        help_text_default: 'When true, Mattermost can act as an OAuth 2.0 service provider allowing Mattermost to authorize API requests from external applications. See [documentation](!https://docs.mattermost.com/developer/oauth-2-0-applications.html) to learn more.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_PERMISSION,
                        key: 'ServiceSettings.EnableOnlyAdminIntegrations',
                        label: t('admin.service.integrationAdmin'),
                        label_default: 'Restrict managing integrations to Admins:',
                        help_text: t('admin.service.integrationAdminDesc'),
                        help_text_default: 'When true, webhooks and slash commands can only be created, edited and viewed by Team and System Admins, and OAuth 2.0 applications by System Admins. Integrations are available to all users after they have been created by the Admin.',
                        permissions_mapping_name: 'enableOnlyAdminIntegrations',
                        isHidden: it.licensed,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnablePostUsernameOverride',
                        label: t('admin.service.overrideTitle'),
                        label_default: 'Enable integrations to override usernames:',
                        help_text: t('admin.service.overrideDescription'),
                        help_text_default: 'When true, webhooks, slash commands and other integrations, such as [Zapier](!https://docs.mattermost.com/integrations/zapier.html), will be allowed to change the username they are posting as. Note: Combined with allowing integrations to override profile picture icons, users may be able to perform phishing attacks by attempting to impersonate other users.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnablePostIconOverride',
                        label: t('admin.service.iconTitle'),
                        label_default: 'Enable integrations to override profile picture icons:',
                        help_text: t('admin.service.iconDescription'),
                        help_text_default: 'When true, webhooks, slash commands and other integrations, such as [Zapier](!https://docs.mattermost.com/integrations/zapier.html), will be allowed to change the profile picture they post with. Note: Combined with allowing integrations to override usernames, users may be able to perform phishing attacks by attempting to impersonate other users.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableUserAccessTokens',
                        label: t('admin.service.userAccessTokensTitle'),
                        label_default: 'Enable User Access Tokens: ',
                        help_text: t('admin.service.userAccessTokensDescription'),
                        help_text_default: 'When true, users can create [user access tokens](!https://about.mattermost.com/default-user-access-tokens) for integrations in **Account Settings > Security**. They can be used to authenticate against the API and give full access to the account.\n\n To manage who can create personal access tokens or to search users by token ID, go to the **User Management > Users** page.',
                        help_text_markdown: true,
                    },
                ],
            },
        },
        bot_accounts: {
            url: 'integrations/bot_accounts',
            title: t('admin.integrations.botAccounts'),
            title_default: 'Bot Accounts',
            schema: {
                id: 'BotAccountSettings',
                name: t('admin.integrations.botAccounts.title'),
                name_default: 'Bot Accounts',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableBotAccountCreation',
                        label: t('admin.service.enableBotTitle'),
                        label_default: 'Enable Bot Account Creation: ',
                        help_text: t('admin.service.enableBotAccountCreation'),
                        help_text_default: 'When true, System Admins can create bot accounts for integrations in [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots). Bot accounts are similar to user accounts except they cannot be used to log in. See [documentation](https://mattermost.com/pl/default-bot-accounts) to learn more.',
                        help_text_markdown: true,
                        help_text_values: {siteURL: getSiteURL()},
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.DisableBotsWhenOwnerIsDeactivated',
                        label: t('admin.service.disableBotOwnerDeactivatedTitle'),
                        label_default: 'Disable bot accounts when owner is deactivated:',
                        help_text: t('admin.service.disableBotWhenOwnerIsDeactivated'),
                        help_text_default: 'When a user is deactivated, disables all bot accounts managed by the user. To re-enable bot accounts, go to [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots).',
                        help_text_markdown: true,
                        help_text_values: {siteURL: getSiteURL()},
                    },
                ],
            },
        },
        gif: {
            url: 'integrations/gif',
            title: t('admin.sidebar.gif'),
            title_default: 'GIF (Beta)',
            schema: {
                id: 'GifSettings',
                name: t('admin.integrations.gif'),
                name_default: 'GIF (Beta)',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableGifPicker',
                        label: t('admin.customization.enableGifPickerTitle'),
                        label_default: 'Enable GIF Picker:',
                        help_text: t('admin.customization.enableGifPickerDesc'),
                        help_text_default: 'Allow users to select GIFs from the emoji picker via a Gfycat integration.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.GfycatApiKey',
                        label: t('admin.customization.gfycatApiKey'),
                        label_default: 'Gfycat API Key:',
                        help_text: t('admin.customization.gfycatApiKeyDescription'),
                        help_text_default: 'Request an API key at [https://developers.gfycat.com/signup/#](!https://developers.gfycat.com/signup/#). Enter the client ID you receive via email to this field. When blank, uses the default API key provided by Gfycat.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.GfycatApiSecret',
                        label: t('admin.customization.gfycatApiSecret'),
                        label_default: 'Gfycat API Secret:',
                        help_text: t('admin.customization.gfycatApiSecretDescription'),
                        help_text_default: 'The API secret generated by Gfycat for your API key. When blank, uses the default API secret provided by Gfycat.',
                    },
                ],
            },
        },
        cors: {
            url: 'integrations/cors',
            title: t('admin.sidebar.cors'),
            title_default: 'CORS',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            schema: {
                id: 'CORS',
                name: t('admin.integrations.cors'),
                name_default: 'CORS',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.AllowCorsFrom',
                        label: t('admin.service.corsTitle'),
                        label_default: 'Enable cross-origin requests from:',
                        placeholder: t('admin.service.corsEx'),
                        placeholder_default: 'http://example.com',
                        help_text: t('admin.service.corsDescription'),
                        help_text_default: 'Enable HTTP Cross origin request from a specific domain. Use "*" if you want to allow CORS from any domain or leave it blank to disable it. Should not be set to "*" in production.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ServiceSettings.CorsExposedHeaders',
                        label: t('admin.service.corsExposedHeadersTitle'),
                        label_default: 'CORS Exposed Headers:',
                        placeholder: t('admin.service.corsHeadersEx'),
                        placeholder_default: 'X-My-Header',
                        help_text: t('admin.service.corsExposedHeadersDescription'),
                        help_text_default: 'Whitelist of headers that will be accessible to the requester.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.CorsAllowCredentials',
                        label: t('admin.service.corsAllowCredentialsLabel'),
                        label_default: 'CORS Allow Credentials:',
                        help_text: t('admin.service.corsAllowCredentialsDescription'),
                        help_text_default: 'When true, requests that pass validation will include the Access-Control-Allow-Credentials header.',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.CorsDebug',
                        label: t('admin.service.CorsDebugLabel'),
                        label_default: 'CORS Debug:',
                        help_text: t('admin.service.corsDebugDescription'),
                        help_text_default: 'When true, prints messages to the logs to help when developing an integration that uses CORS. These messages will include the structured key value pair "source":"cors".',
                    },
                ],
            },
        },
    },
    compliance: {
        icon: 'fa-list',
        sectionTitle: t('admin.sidebar.compliance'),
        sectionTitleDefault: 'Compliance',
        data_retention: {
            url: 'compliance/data_retention',
            title: t('admin.sidebar.dataRetentionPolicy'),
            title_default: 'Data Retention Policy',
            isHidden: it.isnt(it.licensedForFeature('DataRetention')),
            searchableStrings: [
                'admin.data_retention.title',
                'admin.data_retention.messageRetentionDays.description',
                'admin.data_retention.fileRetentionDays.description',
                ['admin.data_retention.note.description', {documentationLink: ''}],
                'admin.data_retention.enableMessageDeletion.title',
                'admin.data_retention.enableMessageDeletion.description',
                'admin.data_retention.enableFileDeletion.title',
                'admin.data_retention.enableFileDeletion.description',
                'admin.data_retention.deletionJobStartTime.title',
                'admin.data_retention.deletionJobStartTime.description',
                'admin.data_retention.createJob.title',
                'admin.data_retention.createJob.help',
            ],
            schema: {
                id: 'DataRetentionSettings',
                component: DataRetentionSettings,
            },
        },
        message_export: {
            url: 'compliance/export',
            title: t('admin.sidebar.complianceExport'),
            title_default: 'Compliance Export (Beta)',
            isHidden: it.isnt(it.licensedForFeature('MessageExport')),
            searchableStrings: [
                'admin.service.complianceExportTitle',
                'admin.service.complianceExportDesc',
                'admin.complianceExport.exportJobStartTime.title',
                'admin.complianceExport.exportJobStartTime.description',
                'admin.complianceExport.exportFormat.title',
                ['admin.complianceExport.exportFormat.description', {siteURL: ''}],
                'admin.complianceExport.createJob.title',
                'admin.complianceExport.createJob.help',
                'admin.complianceExport.globalRelayCustomerType.title',
                'admin.complianceExport.globalRelayCustomerType.description',
                'admin.complianceExport.globalRelaySmtpUsername.title',
                'admin.complianceExport.globalRelaySmtpUsername.description',
                'admin.complianceExport.globalRelaySmtpPassword.title',
                'admin.complianceExport.globalRelaySmtpPassword.description',
                'admin.complianceExport.globalRelayEmailAddress.title',
                'admin.complianceExport.globalRelayEmailAddress.description',
            ],
            schema: {
                id: 'MessageExportSettings',
                component: MessageExportSettings,
            },
        },
        audits: {
            url: 'compliance/monitoring',
            title: t('admin.sidebar.complianceMonitoring'),
            title_default: 'Compliance Monitoring',
            isHidden: it.isnt(it.licensed),
            searchableStrings: [
                'admin.audits.title',
                'admin.audits.reload',
            ],
            schema: {
                id: 'Audits',
                name: t('admin.compliance.complianceMonitoring'),
                name_default: 'Compliance Monitoring',
                component: Audits,
                isHidden: it.isnt(it.licensedForFeature('Compliance')),
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_BANNER,
                        label: t('admin.compliance.newComplianceExportBanner'),
                        label_markdown: true,
                        label_default: 'This feature is replaced by a new [Compliance Export]({siteURL}/admin_console/compliance/export) feature, and will be removed in a future release. We recommend migrating to the new system.',
                        label_values: {siteURL: getSiteURL()},
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                        banner_type: 'info',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ComplianceSettings.Enable',
                        label: t('admin.compliance.enableTitle'),
                        label_default: 'Enable Compliance Reporting:',
                        help_text: t('admin.compliance.enableDesc'),
                        help_text_default: 'When true, Mattermost allows compliance reporting from the **Compliance and Auditing** tab. See [documentation](!https://docs.mattermost.com/administration/compliance.html) to learn more.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'ComplianceSettings.Directory',
                        label: t('admin.compliance.directoryTitle'),
                        label_default: 'Compliance Report Directory:',
                        help_text: t('admin.compliance.directoryDescription'),
                        help_text_default: 'Directory to which compliance reports are written. If blank, will be set to ./data/.',
                        placeholder: t('admin.compliance.directoryExample'),
                        placeholder_default: 'E.g.: "./data/"',
                        isDisabled: it.stateIsFalse('ComplianceSettings.Enable'),
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ComplianceSettings.EnableDaily',
                        label: t('admin.compliance.enableDailyTitle'),
                        label_default: 'Enable Daily Report:',
                        help_text: t('admin.compliance.enableDailyDesc'),
                        help_text_default: 'When true, Mattermost will generate a daily compliance report.',
                        isDisabled: it.stateIsFalse('ComplianceSettings.Enable'),
                        isHidden: it.isnt(it.licensedForFeature('Compliance')),
                    },
                ],
            },
        },
        custom_terms_of_service: {
            url: 'compliance/custom_terms_of_service',
            title: t('admin.sidebar.customTermsOfService'),
            title_default: 'Custom Terms of Service (Beta)',
            isHidden: it.isnt(it.licensedForFeature('CustomTermsOfService')),
            searchableStrings: [
                'admin.support.termsOfServiceTitle',
                'admin.support.enableTermsOfServiceTitle',
                'admin.support.enableTermsOfServiceHelp',
                'admin.support.termsOfServiceTextTitle',
                'admin.support.termsOfServiceTextHelp',
                'admin.support.termsOfServiceReAcceptanceTitle',
                'admin.support.termsOfServiceReAcceptanceHelp',
            ],
            schema: {
                id: 'TermsOfServiceSettings',
                component: CustomTermsOfServiceSettings,
            },
        },
    },
    experimental: {
        icon: 'fa-flask',
        sectionTitle: t('admin.sidebar.experimental'),
        sectionTitleDefault: 'Experimental',
        experimental_features: {
            url: 'experimental/features',
            title: t('admin.sidebar.experimentalFeatures'),
            title_default: 'Features',
            schema: {
                id: 'ExperimentalSettings',
                name: t('admin.experimental.experimentalFeatures'),
                name_default: 'Experimental Features',
                settings: [
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LoginButtonColor',
                        label: t('admin.experimental.ldapSettingsLoginButtonColor.title'),
                        label_default: 'AD/LDAP Login Button Color:',
                        help_text: t('admin.experimental.ldapSettingsLoginButtonColor.desc'),
                        help_text_default: 'Specify the color of the AD/LDAP login button for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensedForFeature('LDAP')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LoginButtonBorderColor',
                        label: t('admin.experimental.ldapSettingsLoginButtonBorderColor.title'),
                        label_default: 'AD/LDAP Login Button Border Color:',
                        help_text: t('admin.experimental.ldapSettingsLoginButtonBorderColor.desc'),
                        help_text_default: 'Specify the color of the AD/LDAP login button border for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensedForFeature('LDAP')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'LdapSettings.LoginButtonTextColor',
                        label: t('admin.experimental.ldapSettingsLoginButtonTextColor.title'),
                        label_default: 'AD/LDAP Login Button Text Color:',
                        help_text: t('admin.experimental.ldapSettingsLoginButtonTextColor.desc'),
                        help_text_default: 'Specify the color of the AD/LDAP login button text for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensedForFeature('LDAP')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.ExperimentalEnableAuthenticationTransfer',
                        label: t('admin.experimental.experimentalEnableAuthenticationTransfer.title'),
                        label_default: 'Allow Authentication Transfer:',
                        help_text: t('admin.experimental.experimentalEnableAuthenticationTransfer.desc'),
                        help_text_default: 'When true, users can change their sign-in method to any that is enabled on the server, either via Account Settings or the APIs. When false, Users cannot change their sign-in method, regardless of which authentication options are enabled.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensed), // documented as E20 and higher, but only E10 in the code
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.CloseUnusedDirectMessages',
                        label: t('admin.experimental.closeUnusedDirectMessages.title'),
                        label_default: 'Autoclose Direct Messages in Sidebar:',
                        help_text: t('admin.experimental.closeUnusedDirectMessages.desc'),
                        help_text_default: 'When true, direct message conversations with no activity for 7 days will be hidden from the sidebar. When false, conversations remain in the sidebar until they are manually closed.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'ExperimentalSettings.LinkMetadataTimeoutMilliseconds',
                        label: t('admin.experimental.linkMetadataTimeoutMilliseconds.title'),
                        label_default: 'Link Metadata Timeout:',
                        help_text: t('admin.experimental.linkMetadataTimeoutMilliseconds.desc'),
                        help_text_default: 'The number of milliseconds to wait for metadata from a third-party link. Used with Post Metadata.',
                        help_text_markdown: false,
                        placeholder: t('admin.experimental.linkMetadataTimeoutMilliseconds.example'),
                        placeholder_default: 'E.g.: "5000"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'EmailSettings.EmailBatchingBufferSize',
                        label: t('admin.experimental.emailBatchingBufferSize.title'),
                        label_default: 'Email Batching Buffer Size:',
                        help_text: t('admin.experimental.emailBatchingBufferSize.desc'),
                        help_text_default: 'Specify the maximum number of notifications batched into a single email.',
                        help_text_markdown: false,
                        placeholder: t('admin.experimental.emailBatchingBufferSize.example'),
                        placeholder_default: 'E.g.: "256"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'EmailSettings.EmailBatchingInterval',
                        label: t('admin.experimental.emailBatchingInterval.title'),
                        label_default: 'Email Batching Interval:',
                        help_text: t('admin.experimental.emailBatchingInterval.desc'),
                        help_text_default: 'Specify the maximum frequency, in seconds, which the batching job checks for new notifications. Longer batching intervals will increase performance.',
                        help_text_markdown: false,
                        placeholder: t('admin.experimental.emailBatchingInterval.example'),
                        placeholder_default: 'E.g.: "30"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.LoginButtonColor',
                        label: t('admin.experimental.emailSettingsLoginButtonColor.title'),
                        label_default: 'Email Login Button Color:',
                        help_text: t('admin.experimental.emailSettingsLoginButtonColor.desc'),
                        help_text_default: 'Specify the color of the email login button for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.LoginButtonBorderColor',
                        label: t('admin.experimental.emailSettingsLoginButtonBorderColor.title'),
                        label_default: 'Email Login Button Border Color:',
                        help_text: t('admin.experimental.emailSettingsLoginButtonBorderColor.desc'),
                        help_text_default: 'Specify the color of the email login button border for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'EmailSettings.LoginButtonTextColor',
                        label: t('admin.experimental.emailSettingsLoginButtonTextColor.title'),
                        label_default: 'Email Login Button Text Color:',
                        help_text: t('admin.experimental.emailSettingsLoginButtonTextColor.desc'),
                        help_text_default: 'Specify the color of the email login button text for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.EnableUserDeactivation',
                        label: t('admin.experimental.enableUserDeactivation.title'),
                        label_default: 'Enable Account Deactivation:',
                        help_text: t('admin.experimental.enableUserDeactivation.desc'),
                        help_text_default: 'When true, users may deactivate their own account from **Account Settings > Advanced**. If a user deactivates their own account, they will get an email notification confirming they were deactivated. When false, users may not deactivate their own account.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.ExperimentalEnableAutomaticReplies',
                        label: t('admin.experimental.experimentalEnableAutomaticReplies.title'),
                        label_default: 'Enable Automatic Replies:',
                        help_text: t('admin.experimental.experimentalEnableAutomaticReplies.desc'),
                        help_text_default: 'When true, users can enable Automatic Replies in **Account Settings > Notifications**. Users set a custom message that will be automatically sent in response to Direct Messages. When false, disables the Automatic Direct Message Replies feature and hides it from Account Settings.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableChannelViewedMessages',
                        label: t('admin.experimental.enableChannelViewedMessages.title'),
                        label_default: 'Enable Channel Viewed WebSocket Messages:',
                        help_text: t('admin.experimental.enableChannelViewedMessages.desc'),
                        help_text_default: 'This setting determines whether `channel_viewed` WebSocket events are sent, which synchronize unread notifications across clients and devices. Disabling the setting in larger deployments may improve server performance.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ExperimentalSettings.ClientSideCertEnable',
                        label: t('admin.experimental.clientSideCertEnable.title'),
                        label_default: 'Enable Client-Side Certification:',
                        help_text: t('admin.experimental.clientSideCertEnable.desc'),
                        help_text_default: 'Enables client-side certification for your Mattermost server. See [documentation](!https://docs.mattermost.com/deployment/certificate-based-authentication.html) to learn more.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensedForFeature('SAML')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'ExperimentalSettings.ClientSideCertCheck',
                        label: t('admin.experimental.clientSideCertCheck.title'),
                        label_default: 'Client-Side Certification Login Method:',
                        help_text: t('admin.experimental.clientSideCertCheck.desc'),
                        help_text_default: 'When **primary**, after the client side certificate is verified, user’s email is retrieved from the certificate and is used to log in without a password. When **secondary**, after the client side certificate is verified, user’s email is retrieved from the certificate and matched against the one supplied by the user. If they match, the user logs in with regular email/password credentials.',
                        help_text_markdown: true,
                        options: [
                            {
                                value: 'primary',
                                display_name: 'primary',
                                display_name_default: 'primary',
                            },
                            {
                                value: 'secondary',
                                display_name: 'secondary',
                                display_name_default: 'secondary',
                            },
                        ],
                        isDisabled: it.stateIsFalse('ExperimentalSettings.ClientSideCertEnable'),
                        isHidden: it.isnt(it.licensedForFeature('SAML')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages',
                        label: t('admin.experimental.experimentalEnableDefaultChannelLeaveJoinMessages.title'),
                        label_default: 'Enable Default Channel Leave/Join System Messages:',
                        help_text: t('admin.experimental.experimentalEnableDefaultChannelLeaveJoinMessages.desc'),
                        help_text_default: 'This setting determines whether team leave/join system messages are posted in the default town-square channel.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.ExperimentalEnableHardenedMode',
                        label: t('admin.experimental.experimentalEnableHardenedMode.title'),
                        label_default: 'Enable Hardened Mode:',
                        help_text: t('admin.experimental.experimentalEnableHardenedMode.desc'),
                        help_text_default: 'Enables a hardened mode for Mattermost that makes user experience trade-offs in the interest of security. See [documentation](!https://docs.mattermost.com/administration/config-settings.html#enable-hardened-mode-experimental) to learn more.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnablePreviewFeatures',
                        label: t('admin.experimental.enablePreviewFeatures.title'),
                        label_default: 'Enable Preview Features:',
                        help_text: t('admin.experimental.enablePreviewFeatures.desc'),
                        help_text_default: 'When true, preview features can be enabled from **Account Settings > Advanced > Preview pre-release features**. When false, disables and hides preview features from **Account Settings > Advanced > Preview pre-release features**.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ThemeSettings.EnableThemeSelection',
                        label: t('admin.experimental.enableThemeSelection.title'),
                        label_default: 'Enable Theme Selection:',
                        help_text: t('admin.experimental.enableThemeSelection.desc'),
                        help_text_default: 'Enables the **Display > Theme** tab in Account Settings so users can select their theme.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensed), // E10 and higher
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ThemeSettings.AllowCustomThemes',
                        label: t('admin.experimental.allowCustomThemes.title'),
                        label_default: 'Allow Custom Themes:',
                        help_text: t('admin.experimental.allowCustomThemes.desc'),
                        help_text_default: 'Enables the **Display > Theme > Custom Theme** section in Account Settings.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensed), // E10 and higher
                        isDisabled: it.stateIsFalse('ThemeSettings.EnableThemeSelection'),
                    },

                    // {
                    //     type: Constants.SettingsTypes.TYPE_LIST,
                    //     key: 'ThemeSettings.AllowedThemes',
                    //     label: t('admin.experimental.allowedThemes.title'),
                    //     label_default: 'Allowed Themes:',
                    //     help_text: t('admin.experimental.allowedThemes.desc'),
                    //     help_text_default: 'A comma-separated list of themes that can be chosen by users when "EnableThemeSelection" is set to true.',
                    //     help_text_markdown: true,
                    //     placeholder: t('admin.experimental.allowedThemes.example'),
                    //     placeholder_default: 'E.g.: "default, organization, mattermostDark, windows10"',
                    //     isHidden: it.isnt(it.licensed), // E10 and higher
                    //     isDisabled: it.stateIsTrue('ThemeSettings.EnableThemeSelection'),
                    // },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'ThemeSettings.DefaultTheme',
                        label: t('admin.experimental.defaultTheme.title'),
                        label_default: 'Default Theme:',
                        help_text: t('admin.experimental.defaultTheme.desc'),
                        help_text_default: 'Set a default theme that applies to all new users on the system.',
                        help_text_markdown: true,
                        options: [
                            {
                                value: 'default',
                                display_name: 'Mattermost',
                                display_name_default: 'Mattermost',
                            },
                            {
                                value: 'organization',
                                display_name: 'Organization',
                                display_name_default: 'Organization',
                            },
                            {
                                value: 'mattermostDark',
                                display_name: 'Mattermost Dark',
                                display_name_default: 'Mattermost Dark',
                            },
                            {
                                value: 'windows10',
                                display_name: 'Windows Dark',
                                display_name_default: 'Windows Dark',
                            },
                        ],
                        isHidden: it.isnt(it.licensed), // E10 and higher
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableTutorial',
                        label: t('admin.experimental.enableTutorial.title'),
                        label_default: 'Enable Tutorial:',
                        help_text: t('admin.experimental.enableTutorial.desc'),
                        help_text_default: 'When true, users are prompted with a tutorial when they open Mattermost for the first time after account creation. When false, the tutorial is disabled, and users are placed in Town Square when they open Mattermost for the first time after account creation.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.EnableUserTypingMessages',
                        label: t('admin.experimental.enableUserTypingMessages.title'),
                        label_default: 'Enable User Typing Messages:',
                        help_text: t('admin.experimental.enableUserTypingMessages.desc'),
                        help_text_default: 'This setting determines whether "user is typing..." messages are displayed below the message box. Disabling the setting in larger deployments may improve server performance.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds',
                        label: t('admin.experimental.timeBetweenUserTypingUpdatesMilliseconds.title'),
                        label_default: 'User Typing Timeout:',
                        help_text: t('admin.experimental.timeBetweenUserTypingUpdatesMilliseconds.desc'),
                        help_text_default: 'The number of milliseconds to wait between emitting user typing websocket events.',
                        help_text_markdown: false,
                        placeholder: t('admin.experimental.timeBetweenUserTypingUpdatesMilliseconds.example'),
                        placeholder_default: 'E.g.: "5000"',
                        isDisabled: it.stateIsFalse('ServiceSettings.EnableUserTypingMessages'),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.EnableXToLeaveChannelsFromLHS',
                        label: t('admin.experimental.enableXToLeaveChannelsFromLHS.title'),
                        label_default: 'Enable X to Leave Channels from Left-Hand Sidebar:',
                        help_text: t('admin.experimental.enableXToLeaveChannelsFromLHS.desc'),
                        help_text_default: 'When true, users can leave Public and Private Channels by clicking the “x” beside the channel name. When false, users must use the **Leave Channel** option from the channel menu to leave channels.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'TeamSettings.ExperimentalPrimaryTeam',
                        label: t('admin.experimental.experimentalPrimaryTeam.title'),
                        label_default: 'Primary Team:',
                        help_text: t('admin.experimental.experimentalPrimaryTeam.desc'),
                        help_text_default: 'The primary team of which users on the server are members. When a primary team is set, the options to join other teams or leave the primary team are disabled.',
                        help_text_markdown: true,
                        placeholder: t('admin.experimental.experimentalPrimaryTeam.example'),
                        placeholder_default: 'E.g.: "teamname"',
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ExperimentalSettings.UseNewSAMLLibrary',
                        label: t('admin.experimental.experimentalUseNewSAMLLibrary.title'),
                        label_default: 'Use Improved SAML Library (Beta):',
                        help_text: t('admin.experimental.experimentalUseNewSAMLLibrary.desc'),
                        help_text_default: 'Enable an updated SAML Library, which does not require the XML Security Library (xmlsec1) to be installed. Warning: Not all providers have been tested. If you experience issues, please contact support: [https://about.mattermost.com/support/](!https://about.mattermost.com/support/). Changing this setting requires a server restart before taking effect.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensedForFeature('SAML')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.LoginButtonColor',
                        label: t('admin.experimental.samlSettingsLoginButtonColor.title'),
                        label_default: 'SAML Login Button Color:',
                        help_text: t('admin.experimental.samlSettingsLoginButtonColor.desc'),
                        help_text_default: 'Specify the color of the SAML login button for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensedForFeature('SAML')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.LoginButtonBorderColor',
                        label: t('admin.experimental.samlSettingsLoginButtonBorderColor.title'),
                        label_default: 'SAML Login Button Border Color:',
                        help_text: t('admin.experimental.samlSettingsLoginButtonBorderColor.desc'),
                        help_text_default: 'Specify the color of the SAML login button border for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensedForFeature('SAML')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_TEXT,
                        key: 'SamlSettings.LoginButtonTextColor',
                        label: t('admin.experimental.samlSettingsLoginButtonTextColor.title'),
                        label_default: 'SAML Login Button Text Color:',
                        help_text: t('admin.experimental.samlSettingsLoginButtonTextColor.desc'),
                        help_text_default: 'Specify the color of the SAML login button text for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.',
                        help_text_markdown: false,
                        isHidden: it.isnt(it.licensedForFeature('SAML')),
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_DROPDOWN,
                        key: 'ServiceSettings.ExperimentalChannelSidebarOrganization',
                        label: t('admin.experimental.experimentalChannelSidebarOrganization.title'),
                        label_default: 'Experimental Sidebar Features',
                        help_text: t('admin.experimental.experimentalChannelSidebarOrganization.desc'),
                        help_text_default: 'When enabled, users can access experimental channel sidebar features, including collapsible sections and unreads filtering. If default on, this enabled the new sidebar features by default for all users on this server. Users can disable the features in **Account Settings > Sidebar > Experimental Sidebar Features**. If default off, users must enable the experimental sidebar features in Account Settings. [Learn more](!https://about.mattermost.com/default-sidebar/) or [give us feedback](!https://about.mattermost.com/default-sidebar-survey/)',
                        help_text_markdown: true,
                        options: [
                            {
                                value: 'disabled',
                                display_name: t('admin.experimental.experimentalChannelSidebarOrganization.disabled'),
                                display_name_default: 'Disabled',
                            },
                            {
                                value: 'default_on',
                                display_name: t('admin.experimental.experimentalChannelSidebarOrganization.default_on'),
                                display_name_default: 'Enabled (Default On)',
                            },
                            {
                                value: 'default_off',
                                display_name: t('admin.experimental.experimentalChannelSidebarOrganization.default_off'),
                                display_name_default: 'Enabled (Default Off)',
                            },
                        ],
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'ServiceSettings.ExperimentalChannelOrganization',
                        label: t('admin.experimental.experimentalChannelOrganization.title'),
                        label_default: 'Channel Grouping and Sorting',
                        help_text: t('admin.experimental.experimentalChannelOrganization.desc'),
                        help_text_default: 'Enables channel sidebar organization options in **Account Settings > Sidebar > Channel grouping and sorting** including options for grouping unread channels, sorting channels by most recent post and combining all channel types into a single list. These settings are not available if **Account Settings > Sidebar > Experimental Sidebar Features** are enabled.',
                        help_text_markdown: true,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'DisplaySettings.ExperimentalDataPrefetch',
                        label: t('admin.experimental.experimentalDataPrefetch.title'),
                        label_default: 'Preload messages in unread channels:',
                        help_text: t('admin.experimental.experimentalDataPrefetch.desc'),
                        help_text_default: 'When true, messages in unread channels are preloaded to reduce channel loading time. When false, messages are not loaded from the server until users switch channels.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'DisplaySettings.ExperimentalTimezone',
                        label: t('admin.experimental.experimentalTimezone.title'),
                        label_default: 'Timezone:',
                        help_text: t('admin.experimental.experimentalTimezone.desc'),
                        help_text_default: 'Select the timezone used for timestamps in the user interface and email notifications. When true, the Timezone setting is visible in the Account Settings and a time zone is automatically assigned in the next active session. When false, the Timezone setting is hidden in the Account Settings.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.ExperimentalHideTownSquareinLHS',
                        label: t('admin.experimental.experimentalHideTownSquareinLHS.title'),
                        label_default: 'Town Square is Hidden in Left-Hand Sidebar:',
                        help_text: t('admin.experimental.experimentalHideTownSquareinLHS.desc'),
                        help_text_default: 'When true, hides Town Square in the left-hand sidebar if there are no unread messages in the channel. When false, Town Square is always visible in the left-hand sidebar even if all messages have been read.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensed), // E10 and higher
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'TeamSettings.ExperimentalTownSquareIsReadOnly',
                        label: t('admin.experimental.experimentalTownSquareIsReadOnly.title'),
                        label_default: 'Town Square is Read-Only:',
                        help_text: t('admin.experimental.experimentalTownSquareIsReadOnly.desc'),
                        help_text_default: 'When true, only System Admins can post in Town Square. Other members are not able to post, reply, upload files, emoji react or pin messages to Town Square, nor are they able to change the channel name, header or purpose. When false, anyone can post in Town Square.',
                        help_text_markdown: true,
                        isHidden: it.isnt(it.licensed), // E10 and higher
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_BOOL,
                        key: 'EmailSettings.UseChannelInEmailNotifications',
                        label: t('admin.experimental.useChannelInEmailNotifications.title'),
                        label_default: 'Use Channel Name in Email Notifications:',
                        help_text: t('admin.experimental.useChannelInEmailNotifications.desc'),
                        help_text_default: 'When true, channel and team name appears in email notification subject lines. Useful for servers using only one team. When false, only team name appears in email notification subject line.',
                        help_text_markdown: false,
                    },
                    {
                        type: Constants.SettingsTypes.TYPE_NUMBER,
                        key: 'TeamSettings.UserStatusAwayTimeout',
                        label: t('admin.experimental.userStatusAwayTimeout.title'),
                        label_default: 'User Status Away Timeout:',
                        help_text: t('admin.experimental.userStatusAwayTimeout.desc'),
                        help_text_default: 'This setting defines the number of seconds after which the user’s status indicator changes to "Away", when they are away from Mattermost.',
                        help_text_markdown: false,
                        placeholder: t('admin.experimental.userStatusAwayTimeout.example'),
                        placeholder_default: 'E.g.: "300"',
                    }, // eslint-disable-next-line lines-around-comment
                    // {
                    //     type: Constants.SettingsTypes.TYPE_BOOL,
                    //     key: 'ServiceSettings.ExperimentalStrictCSRFEnforcement',
                    //     label: t('admin.experimental.experimentalStrictCSRFEnforcement.title'),
                    //     label_default: 'TODO:',
                    //     help_text: t('admin.experimental.experimentalStrictCSRFEnforcement.desc'),
                    //     help_text_default: 'TODO',
                    //     help_text_markdown: false,
                    // },
                    // {
                    //     type: Constants.SettingsTypes.TYPE_LIST,
                    //     key: 'TeamSettings.ExperimentalDefaultChannels',
                    //     label: t('admin.experimental.experimentalDefaultChannels.title'),
                    //     label_default: 'Default Channels:',
                    //     help_text: t('admin.experimental.experimentalDefaultChannels.desc'),
                    //     help_text_default: 'A comma-separated list of default channels every user is added to automatically after joining a new team. Only applies to public channels, but affects all teams on the server. When not set, every user is added to `off-topic` and `town-square` channel by default. Note that even if `town-square` is not listed, every user is added to that channel after joining a new team.',
                    //     help_text_markdown: true,
                    //     placeholder: t('admin.experimental.experimentalDefaultChannels.example'),
                    //     placeholder_default: 'E.g.: "channel1, channel2, off-topic"',
                    // },
                    // {
                    //     type: Constants.SettingsTypes.TYPE_TEXT,
                    //     key: 'EmailSettings.ReplyToAddress',
                    //     label: t('admin.experimental.replyToAddress.title'),
                    //     label_default: 'Reply To Address:',
                    //     help_text: t('admin.experimental.replyToAddress.desc'),
                    //     help_text_default: 'TODO',
                    //     help_text_markdown: true,
                    //     placeholder: t('admin.experimental.replyToAddress.example'),
                    //     placeholder_default: 'E.g.: "reply-to@example.com"',
                    // },
                ],
            },
        },
        bleve: {
            url: 'experimental/blevesearch',
            title: t('admin.sidebar.blevesearch'),
            title_default: 'Bleve',
            isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
            searchableStrings: [
                'admin.bleve.title',
                'admin.bleve.enableIndexingTitle',
                ['admin.bleve.enableIndexingDescription', {documentationLink: ''}],
                'admin.bleve.enableIndexingDescription.documentationLinkText',
                'admin.bleve.bulkIndexingTitle',
                'admin.bleve.createJob.help',
                'admin.bleve.purgeIndexesHelpText',
                'admin.bleve.purgeIndexesButton',
                'admin.bleve.purgeIndexesButton.label',
                'admin.bleve.enableSearchingTitle',
                'admin.bleve.enableSearchingDescription',
            ],
            schema: {
                id: 'BleveSettings',
                component: BleveSettings,
            },
        },
    },
};

t('admin.field_names.allowBannerDismissal');
t('admin.field_names.bannerColor');
t('admin.field_names.bannerText');
t('admin.field_names.bannerTextColor');
t('admin.field_names.enableBanner');
t('admin.field_names.enableCommands');
t('admin.field_names.enableConfirmNotificationsToChannel');
t('admin.field_names.enableIncomingWebhooks');
t('admin.field_names.enableOAuthServiceProvider');
t('admin.field_names.enableOutgoingWebhooks');
t('admin.field_names.enablePostIconOverride');
t('admin.field_names.enablePostUsernameOverride');
t('admin.field_names.enableUserAccessTokens');
t('admin.field_names.enableUserCreation');
t('admin.field_names.maxChannelsPerTeam');
t('admin.field_names.maxNotificationsPerChannel');
t('admin.field_names.maxUsersPerTeam');
t('admin.field_names.postEditTimeLimit');
t('admin.field_names.restrictCreationToDomains');
t('admin.field_names.restrictDirectMessage');
t('admin.field_names.teammateNameDisplay');

export default AdminDefinition;
